[llvm] [X86][GlobalISel] Support fp80 for G_FPTRUNC and G_FPEXT (PR #141611)

Evgenii Kudriashov via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 17 02:48:01 PST 2026


https://github.com/e-kud updated https://github.com/llvm/llvm-project/pull/141611

>From a603218cf79bd14304479f56f3349c7075e9e696 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Tue, 27 May 2025 06:51:53 -0700
Subject: [PATCH 1/6] Precommit tests

---
 .../CodeGen/X86/GlobalISel/fpext-scalar.ll    |  12 --
 llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll   | 177 ++++++++++++++++++
 2 files changed, 177 insertions(+), 12 deletions(-)
 delete mode 100644 llvm/test/CodeGen/X86/GlobalISel/fpext-scalar.ll
 create mode 100644 llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll

diff --git a/llvm/test/CodeGen/X86/GlobalISel/fpext-scalar.ll b/llvm/test/CodeGen/X86/GlobalISel/fpext-scalar.ll
deleted file mode 100644
index 8501009e2915a..0000000000000
--- a/llvm/test/CodeGen/X86/GlobalISel/fpext-scalar.ll
+++ /dev/null
@@ -1,12 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=CHECK
-
-define double @test(float %a) {
-; CHECK-LABEL: test:
-; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    cvtss2sd %xmm0, %xmm0
-; CHECK-NEXT:    retq
-entry:
-  %conv = fpext float %a to double
-  ret double %conv
-}
diff --git a/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll b/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
new file mode 100644
index 0000000000000..717802110c6a6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
@@ -0,0 +1,177 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown                   -fast-isel=0 -global-isel=0 | FileCheck %s --check-prefixes X86,FASTSDAG-X86,SDAG-X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    -fast-isel=0 -global-isel=0 | FileCheck %s --check-prefixes SSE,FASTSDAG-SSE,SDAG-SSE
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     -fast-isel=0 -global-isel=0 | FileCheck %s --check-prefixes AVX,FASTSDAG-AVX,SDAG-AVX
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=0 -global-isel=0 | FileCheck %s --check-prefixes AVX,FASTSDAG-AVX,SDAG-AVX
+; COMM: FastISel has troubles with fp80 type
+; RUN: llc < %s -mtriple=i686-unknown-unknown                   -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes X86,FASTSDAG-X86,FAST-X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes SSE,FASTSDAG-SSE,FAST-SSE
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes AVX,FASTSDAG-AVX,FAST-AVX
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes AVX,FASTSDAG-AVX,FAST-AVX
+; RUN: llc < %s -mtriple=i686-unknown-unknown                   -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes X86,GLOBAL-X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes SSE,GLOBAL-SSE
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
+
+define double @fpext_float_to_double(float %f) {
+; X86-LABEL: fpext_float_to_double:
+; X86:       # %bb.0:
+; X86-NEXT:    flds {{[0-9]+}}(%esp)
+; X86-NEXT:    retl
+;
+; SSE-LABEL: fpext_float_to_double:
+; SSE:       # %bb.0:
+; SSE-NEXT:    cvtss2sd %xmm0, %xmm0
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: fpext_float_to_double:
+; AVX:       # %bb.0:
+; AVX-NEXT:    vcvtss2sd %xmm0, %xmm0, %xmm0
+; AVX-NEXT:    retq
+  %1 = fpext float %f to double
+  ret double %1
+}
+
+define x86_fp80 @fpext_float_to_x86_fp80(float %f) {
+; X86-LABEL: fpext_float_to_x86_fp80:
+; X86:       # %bb.0:
+; X86-NEXT:    flds {{[0-9]+}}(%esp)
+; X86-NEXT:    retl
+;
+; SSE-LABEL: fpext_float_to_x86_fp80:
+; SSE:       # %bb.0:
+; SSE-NEXT:    movss %xmm0, -{{[0-9]+}}(%rsp)
+; SSE-NEXT:    flds -{{[0-9]+}}(%rsp)
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: fpext_float_to_x86_fp80:
+; AVX:       # %bb.0:
+; AVX-NEXT:    vmovss %xmm0, -{{[0-9]+}}(%rsp)
+; AVX-NEXT:    flds -{{[0-9]+}}(%rsp)
+; AVX-NEXT:    retq
+  %1 = fpext float %f to x86_fp80
+  ret x86_fp80 %1
+}
+
+define x86_fp80 @fpext_double_to_x86_fp80(double %d) {
+; X86-LABEL: fpext_double_to_x86_fp80:
+; X86:       # %bb.0:
+; X86-NEXT:    fldl {{[0-9]+}}(%esp)
+; X86-NEXT:    retl
+;
+; SSE-LABEL: fpext_double_to_x86_fp80:
+; SSE:       # %bb.0:
+; SSE-NEXT:    movsd %xmm0, -{{[0-9]+}}(%rsp)
+; SSE-NEXT:    fldl -{{[0-9]+}}(%rsp)
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: fpext_double_to_x86_fp80:
+; AVX:       # %bb.0:
+; AVX-NEXT:    vmovsd %xmm0, -{{[0-9]+}}(%rsp)
+; AVX-NEXT:    fldl -{{[0-9]+}}(%rsp)
+; AVX-NEXT:    retq
+  %1 = fpext double %d to x86_fp80
+  ret x86_fp80 %1
+}
+
+define float @fptrunc_double_to_float(double %d) {
+; X86-LABEL: fptrunc_double_to_float:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %eax
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    fldl {{[0-9]+}}(%esp)
+; X86-NEXT:    fstps (%esp)
+; X86-NEXT:    flds (%esp)
+; X86-NEXT:    popl %eax
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
+;
+; SSE-LABEL: fptrunc_double_to_float:
+; SSE:       # %bb.0:
+; SSE-NEXT:    cvtsd2ss %xmm0, %xmm0
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: fptrunc_double_to_float:
+; AVX:       # %bb.0:
+; AVX-NEXT:    vcvtsd2ss %xmm0, %xmm0, %xmm0
+; AVX-NEXT:    retq
+  %1 = fptrunc double %d to float
+  ret float %1
+}
+
+define float @fptrunc_x86_fp80_to_float(x86_fp80 %x) {
+; X86-LABEL: fptrunc_x86_fp80_to_float:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %eax
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    fldt {{[0-9]+}}(%esp)
+; X86-NEXT:    fstps (%esp)
+; X86-NEXT:    flds (%esp)
+; X86-NEXT:    popl %eax
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
+;
+; SSE-LABEL: fptrunc_x86_fp80_to_float:
+; SSE:       # %bb.0:
+; SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
+; SSE-NEXT:    fstps -{{[0-9]+}}(%rsp)
+; SSE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: fptrunc_x86_fp80_to_float:
+; AVX:       # %bb.0:
+; AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
+; AVX-NEXT:    fstps -{{[0-9]+}}(%rsp)
+; AVX-NEXT:    vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT:    retq
+  %1 = fptrunc x86_fp80 %x to float
+  ret float %1
+}
+
+define double @fptrunc_x86_fp80_to_double(x86_fp80 %x) {
+; X86-LABEL: fptrunc_x86_fp80_to_double:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %ebp
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %ebp, -8
+; X86-NEXT:    movl %esp, %ebp
+; X86-NEXT:    .cfi_def_cfa_register %ebp
+; X86-NEXT:    andl $-8, %esp
+; X86-NEXT:    subl $8, %esp
+; X86-NEXT:    fldt 8(%ebp)
+; X86-NEXT:    fstpl (%esp)
+; X86-NEXT:    fldl (%esp)
+; X86-NEXT:    movl %ebp, %esp
+; X86-NEXT:    popl %ebp
+; X86-NEXT:    .cfi_def_cfa %esp, 4
+; X86-NEXT:    retl
+;
+; SSE-LABEL: fptrunc_x86_fp80_to_double:
+; SSE:       # %bb.0:
+; SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
+; SSE-NEXT:    fstpl -{{[0-9]+}}(%rsp)
+; SSE-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: fptrunc_x86_fp80_to_double:
+; AVX:       # %bb.0:
+; AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
+; AVX-NEXT:    fstpl -{{[0-9]+}}(%rsp)
+; AVX-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT:    retq
+  %1 = fptrunc x86_fp80 %x to double
+  ret double %1
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; FAST-AVX: {{.*}}
+; FAST-SSE: {{.*}}
+; FAST-X86: {{.*}}
+; FASTSDAG-AVX: {{.*}}
+; FASTSDAG-SSE: {{.*}}
+; FASTSDAG-X86: {{.*}}
+; GLOBAL-AVX: {{.*}}
+; GLOBAL-SSE: {{.*}}
+; GLOBAL-X86: {{.*}}
+; SDAG-AVX: {{.*}}
+; SDAG-SSE: {{.*}}
+; SDAG-X86: {{.*}}

>From cd09cc331958ac543785a7de80ae68a4bd5d7887 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Tue, 27 May 2025 06:57:16 -0700
Subject: [PATCH 2/6] [X86][GlobalISel] Support fp80 for G_FPTRUNC and G_FPEXT

---
 .../lib/Target/X86/GISel/X86LegalizerInfo.cpp |  61 ++++-
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.h  |   3 +
 llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll   | 244 +++++++++++++-----
 3 files changed, 224 insertions(+), 84 deletions(-)

diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index f008cb1bea839..58215d4e00202 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -376,9 +376,15 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
     Action.legalForTypesWithMemDesc({{s8, p0, s8, 1},
                                      {s16, p0, s16, 1},
                                      {s32, p0, s32, 1},
-                                     {s80, p0, s80, 1},
                                      {p0, p0, p0, 1},
                                      {v4s8, p0, v4s8, 1}});
+
+    if (UseX87)
+      Action.legalForTypesWithMemDesc({{s80, p0, s32, 1},
+                                       {s80, p0, s64, 1},
+                                       {s32, p0, s80, 1},
+                                       {s64, p0, s80, 1},
+                                       {s80, p0, s80, 1}});
     if (Is64Bit)
       Action.legalForTypesWithMemDesc(
           {{s64, p0, s64, 1}, {v2s32, p0, v2s32, 1}});
@@ -476,18 +482,17 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
       .widenScalarToNextPow2(1);
 
   // fp conversions
-  getActionDefinitionsBuilder(G_FPEXT).legalIf([=](const LegalityQuery &Query) {
-    return (HasSSE2 && typePairInSet(0, 1, {{s64, s32}})(Query)) ||
-           (HasAVX && typePairInSet(0, 1, {{v4s64, v4s32}})(Query)) ||
-           (HasAVX512 && typePairInSet(0, 1, {{v8s64, v8s32}})(Query));
-  });
-
-  getActionDefinitionsBuilder(G_FPTRUNC).legalIf(
-      [=](const LegalityQuery &Query) {
-        return (HasSSE2 && typePairInSet(0, 1, {{s32, s64}})(Query)) ||
-               (HasAVX && typePairInSet(0, 1, {{v4s32, v4s64}})(Query)) ||
-               (HasAVX512 && typePairInSet(0, 1, {{v8s32, v8s64}})(Query));
-      });
+  getActionDefinitionsBuilder(G_FPEXT)
+      .legalFor(HasSSE2, {{s64, s32}})
+      .legalFor(HasAVX, {{v4s64, v4s32}})
+      .legalFor(HasAVX512, {{v8s64, v8s32}})
+      .customFor(UseX87, {{s64, s32}, {s80, s32}, {s80, s64}});
+
+  getActionDefinitionsBuilder(G_FPTRUNC)
+      .legalFor(HasSSE2, {{s32, s64}})
+      .legalFor(HasAVX, {{v4s32, v4s64}})
+      .legalFor(HasAVX512, {{v8s32, v8s64}})
+      .customFor(UseX87, {{s32, s64}, {s32, s80}, {s64, s80}});
 
   getActionDefinitionsBuilder(G_SITOFP)
       .legalIf([=](const LegalityQuery &Query) {
@@ -671,6 +676,9 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
     return legalizeUITOFP(MI, MRI, Helper);
   case TargetOpcode::G_STORE:
     return legalizeNarrowingStore(MI, MRI, Helper);
+  case TargetOpcode::G_FPEXT:
+  case TargetOpcode::G_FPTRUNC:
+    return legalizeFPExtAndTrunc(MI, MRI, Helper);
   }
   llvm_unreachable("expected switch to return");
 }
@@ -781,6 +789,33 @@ bool X86LegalizerInfo::legalizeNarrowingStore(MachineInstr &MI,
   return true;
 }
 
+bool X86LegalizerInfo::legalizeFPExtAndTrunc(MachineInstr &MI,
+                                             MachineRegisterInfo &MRI,
+                                             LegalizerHelper &Helper) const {
+  assert((MI.getOpcode() == TargetOpcode::G_FPEXT ||
+          MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
+         "Only G_FPEXT and G_FPTRUNC are expected");
+  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
+  MachinePointerInfo PtrInfo;
+  LLT StackTy = MI.getOpcode() == TargetOpcode::G_FPEXT ? SrcTy : DstTy;
+  Align StackTyAlign = Helper.getStackTemporaryAlignment(StackTy);
+  auto StackTemp = Helper.createStackTemporary(StackTy.getSizeInBytes(),
+                                               StackTyAlign, PtrInfo);
+
+  MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
+  MachineFunction &MF = MIRBuilder.getMF();
+  auto *StoreMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
+                                           StackTy, StackTyAlign);
+  MIRBuilder.buildStore(SrcReg, StackTemp, *StoreMMO);
+
+  auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
+                                          StackTy, StackTyAlign);
+  MIRBuilder.buildLoad(DstReg, StackTemp, *LoadMMO);
+
+  MI.eraseFromParent();
+  return true;
+}
+
 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
                                          MachineInstr &MI) const {
   return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 54f776456397b..b224f3f46a2d5 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -48,6 +48,9 @@ class X86LegalizerInfo : public LegalizerInfo {
 
   bool legalizeNarrowingStore(MachineInstr &MI, MachineRegisterInfo &MRI,
                               LegalizerHelper &Helper) const;
+
+  bool legalizeFPExtAndTrunc(MachineInstr &MI, MachineRegisterInfo &MRI,
+                             LegalizerHelper &Helper) const;
 };
 } // namespace llvm
 #endif
diff --git a/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll b/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
index 717802110c6a6..0ad9b90806ce9 100644
--- a/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
+++ b/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
@@ -8,10 +8,11 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes SSE,FASTSDAG-SSE,FAST-SSE
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes AVX,FASTSDAG-AVX,FAST-AVX
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=1 -global-isel=0 -fast-isel-abort=0 | FileCheck %s --check-prefixes AVX,FASTSDAG-AVX,FAST-AVX
+; COMM: GlobalISel can't legalize double stores on 32bit platform due to lack of double/integer distinguish during legalization
 ; RUN: llc < %s -mtriple=i686-unknown-unknown                   -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes X86,GLOBAL-X86
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes SSE,GLOBAL-SSE
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=0 -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    -fast-isel=0 -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefixes SSE,GLOBAL-SSE
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     -fast-isel=0 -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=0 -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
 
 define double @fpext_float_to_double(float %f) {
 ; X86-LABEL: fpext_float_to_double:
@@ -33,58 +34,118 @@ define double @fpext_float_to_double(float %f) {
 }
 
 define x86_fp80 @fpext_float_to_x86_fp80(float %f) {
-; X86-LABEL: fpext_float_to_x86_fp80:
-; X86:       # %bb.0:
-; X86-NEXT:    flds {{[0-9]+}}(%esp)
-; X86-NEXT:    retl
+; FASTSDAG-X86-LABEL: fpext_float_to_x86_fp80:
+; FASTSDAG-X86:       # %bb.0:
+; FASTSDAG-X86-NEXT:    flds {{[0-9]+}}(%esp)
+; FASTSDAG-X86-NEXT:    retl
 ;
-; SSE-LABEL: fpext_float_to_x86_fp80:
-; SSE:       # %bb.0:
-; SSE-NEXT:    movss %xmm0, -{{[0-9]+}}(%rsp)
-; SSE-NEXT:    flds -{{[0-9]+}}(%rsp)
-; SSE-NEXT:    retq
+; FASTSDAG-SSE-LABEL: fpext_float_to_x86_fp80:
+; FASTSDAG-SSE:       # %bb.0:
+; FASTSDAG-SSE-NEXT:    movss %xmm0, -{{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    flds -{{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    retq
 ;
-; AVX-LABEL: fpext_float_to_x86_fp80:
-; AVX:       # %bb.0:
-; AVX-NEXT:    vmovss %xmm0, -{{[0-9]+}}(%rsp)
-; AVX-NEXT:    flds -{{[0-9]+}}(%rsp)
-; AVX-NEXT:    retq
+; FASTSDAG-AVX-LABEL: fpext_float_to_x86_fp80:
+; FASTSDAG-AVX:       # %bb.0:
+; FASTSDAG-AVX-NEXT:    vmovss %xmm0, -{{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    flds -{{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    retq
+;
+; GLOBAL-X86-LABEL: fpext_float_to_x86_fp80:
+; GLOBAL-X86:       # %bb.0:
+; GLOBAL-X86-NEXT:    pushl %eax
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 8
+; GLOBAL-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; GLOBAL-X86-NEXT:    movl %eax, (%esp)
+; GLOBAL-X86-NEXT:    flds (%esp)
+; GLOBAL-X86-NEXT:    popl %eax
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 4
+; GLOBAL-X86-NEXT:    retl
+;
+; GLOBAL-SSE-LABEL: fpext_float_to_x86_fp80:
+; GLOBAL-SSE:       # %bb.0:
+; GLOBAL-SSE-NEXT:    movd %xmm0, %eax
+; GLOBAL-SSE-NEXT:    movl %eax, -{{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    flds -{{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    retq
+;
+; GLOBAL-AVX-LABEL: fpext_float_to_x86_fp80:
+; GLOBAL-AVX:       # %bb.0:
+; GLOBAL-AVX-NEXT:    vmovd %xmm0, %eax
+; GLOBAL-AVX-NEXT:    movl %eax, -{{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    flds -{{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    retq
   %1 = fpext float %f to x86_fp80
   ret x86_fp80 %1
 }
 
 define x86_fp80 @fpext_double_to_x86_fp80(double %d) {
-; X86-LABEL: fpext_double_to_x86_fp80:
-; X86:       # %bb.0:
-; X86-NEXT:    fldl {{[0-9]+}}(%esp)
-; X86-NEXT:    retl
+; FASTSDAG-X86-LABEL: fpext_double_to_x86_fp80:
+; FASTSDAG-X86:       # %bb.0:
+; FASTSDAG-X86-NEXT:    fldl {{[0-9]+}}(%esp)
+; FASTSDAG-X86-NEXT:    retl
 ;
-; SSE-LABEL: fpext_double_to_x86_fp80:
-; SSE:       # %bb.0:
-; SSE-NEXT:    movsd %xmm0, -{{[0-9]+}}(%rsp)
-; SSE-NEXT:    fldl -{{[0-9]+}}(%rsp)
-; SSE-NEXT:    retq
+; FASTSDAG-SSE-LABEL: fpext_double_to_x86_fp80:
+; FASTSDAG-SSE:       # %bb.0:
+; FASTSDAG-SSE-NEXT:    movsd %xmm0, -{{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    fldl -{{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    retq
 ;
-; AVX-LABEL: fpext_double_to_x86_fp80:
-; AVX:       # %bb.0:
-; AVX-NEXT:    vmovsd %xmm0, -{{[0-9]+}}(%rsp)
-; AVX-NEXT:    fldl -{{[0-9]+}}(%rsp)
-; AVX-NEXT:    retq
+; FASTSDAG-AVX-LABEL: fpext_double_to_x86_fp80:
+; FASTSDAG-AVX:       # %bb.0:
+; FASTSDAG-AVX-NEXT:    vmovsd %xmm0, -{{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    fldl -{{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    retq
+;
+; GLOBAL-X86-LABEL: fpext_double_to_x86_fp80:
+; GLOBAL-X86:       # %bb.0:
+; GLOBAL-X86-NEXT:    pushl %ebp
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 8
+; GLOBAL-X86-NEXT:    .cfi_offset %ebp, -8
+; GLOBAL-X86-NEXT:    movl %esp, %ebp
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_register %ebp
+; GLOBAL-X86-NEXT:    andl $-8, %esp
+; GLOBAL-X86-NEXT:    subl $8, %esp
+; GLOBAL-X86-NEXT:    leal 8(%ebp), %eax
+; GLOBAL-X86-NEXT:    movl 8(%ebp), %ecx
+; GLOBAL-X86-NEXT:    movl 4(%eax), %eax
+; GLOBAL-X86-NEXT:    movl %esp, %edx
+; GLOBAL-X86-NEXT:    movl %ecx, (%esp)
+; GLOBAL-X86-NEXT:    movl %eax, 4(%edx)
+; GLOBAL-X86-NEXT:    fldl (%esp)
+; GLOBAL-X86-NEXT:    movl %ebp, %esp
+; GLOBAL-X86-NEXT:    popl %ebp
+; GLOBAL-X86-NEXT:    .cfi_def_cfa %esp, 4
+; GLOBAL-X86-NEXT:    retl
+;
+; GLOBAL-SSE-LABEL: fpext_double_to_x86_fp80:
+; GLOBAL-SSE:       # %bb.0:
+; GLOBAL-SSE-NEXT:    movq %xmm0, %rax
+; GLOBAL-SSE-NEXT:    movq %rax, -{{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    fldl -{{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    retq
+;
+; GLOBAL-AVX-LABEL: fpext_double_to_x86_fp80:
+; GLOBAL-AVX:       # %bb.0:
+; GLOBAL-AVX-NEXT:    vmovq %xmm0, %rax
+; GLOBAL-AVX-NEXT:    movq %rax, -{{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    fldl -{{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    retq
   %1 = fpext double %d to x86_fp80
   ret x86_fp80 %1
 }
 
 define float @fptrunc_double_to_float(double %d) {
-; X86-LABEL: fptrunc_double_to_float:
-; X86:       # %bb.0:
-; X86-NEXT:    pushl %eax
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    fldl {{[0-9]+}}(%esp)
-; X86-NEXT:    fstps (%esp)
-; X86-NEXT:    flds (%esp)
-; X86-NEXT:    popl %eax
-; X86-NEXT:    .cfi_def_cfa_offset 4
-; X86-NEXT:    retl
+; FASTSDAG-X86-LABEL: fptrunc_double_to_float:
+; FASTSDAG-X86:       # %bb.0:
+; FASTSDAG-X86-NEXT:    pushl %eax
+; FASTSDAG-X86-NEXT:    .cfi_def_cfa_offset 8
+; FASTSDAG-X86-NEXT:    fldl {{[0-9]+}}(%esp)
+; FASTSDAG-X86-NEXT:    fstps (%esp)
+; FASTSDAG-X86-NEXT:    flds (%esp)
+; FASTSDAG-X86-NEXT:    popl %eax
+; FASTSDAG-X86-NEXT:    .cfi_def_cfa_offset 4
+; FASTSDAG-X86-NEXT:    retl
 ;
 ; SSE-LABEL: fptrunc_double_to_float:
 ; SSE:       # %bb.0:
@@ -95,6 +156,21 @@ define float @fptrunc_double_to_float(double %d) {
 ; AVX:       # %bb.0:
 ; AVX-NEXT:    vcvtsd2ss %xmm0, %xmm0, %xmm0
 ; AVX-NEXT:    retq
+;
+; GLOBAL-X86-LABEL: fptrunc_double_to_float:
+; GLOBAL-X86:       # %bb.0:
+; GLOBAL-X86-NEXT:    pushl %eax
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 8
+; GLOBAL-X86-NEXT:    leal {{[0-9]+}}(%esp), %eax
+; GLOBAL-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; GLOBAL-X86-NEXT:    movl 4(%eax), %eax
+; GLOBAL-X86-NEXT:    movl %esp, %edx
+; GLOBAL-X86-NEXT:    movl %ecx, (%esp)
+; GLOBAL-X86-NEXT:    movl %eax, 4(%edx)
+; GLOBAL-X86-NEXT:    flds (%esp)
+; GLOBAL-X86-NEXT:    popl %eax
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 4
+; GLOBAL-X86-NEXT:    retl
   %1 = fptrunc double %d to float
   ret float %1
 }
@@ -111,19 +187,35 @@ define float @fptrunc_x86_fp80_to_float(x86_fp80 %x) {
 ; X86-NEXT:    .cfi_def_cfa_offset 4
 ; X86-NEXT:    retl
 ;
-; SSE-LABEL: fptrunc_x86_fp80_to_float:
-; SSE:       # %bb.0:
-; SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
-; SSE-NEXT:    fstps -{{[0-9]+}}(%rsp)
-; SSE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; SSE-NEXT:    retq
+; FASTSDAG-SSE-LABEL: fptrunc_x86_fp80_to_float:
+; FASTSDAG-SSE:       # %bb.0:
+; FASTSDAG-SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    fstps -{{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; FASTSDAG-SSE-NEXT:    retq
 ;
-; AVX-LABEL: fptrunc_x86_fp80_to_float:
-; AVX:       # %bb.0:
-; AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
-; AVX-NEXT:    fstps -{{[0-9]+}}(%rsp)
-; AVX-NEXT:    vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT:    retq
+; FASTSDAG-AVX-LABEL: fptrunc_x86_fp80_to_float:
+; FASTSDAG-AVX:       # %bb.0:
+; FASTSDAG-AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    fstps -{{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; FASTSDAG-AVX-NEXT:    retq
+;
+; GLOBAL-SSE-LABEL: fptrunc_x86_fp80_to_float:
+; GLOBAL-SSE:       # %bb.0:
+; GLOBAL-SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    fstps -{{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    movl -{{[0-9]+}}(%rsp), %eax
+; GLOBAL-SSE-NEXT:    movd %eax, %xmm0
+; GLOBAL-SSE-NEXT:    retq
+;
+; GLOBAL-AVX-LABEL: fptrunc_x86_fp80_to_float:
+; GLOBAL-AVX:       # %bb.0:
+; GLOBAL-AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    fstps -{{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    movl -{{[0-9]+}}(%rsp), %eax
+; GLOBAL-AVX-NEXT:    vmovd %eax, %xmm0
+; GLOBAL-AVX-NEXT:    retq
   %1 = fptrunc x86_fp80 %x to float
   ret float %1
 }
@@ -146,19 +238,35 @@ define double @fptrunc_x86_fp80_to_double(x86_fp80 %x) {
 ; X86-NEXT:    .cfi_def_cfa %esp, 4
 ; X86-NEXT:    retl
 ;
-; SSE-LABEL: fptrunc_x86_fp80_to_double:
-; SSE:       # %bb.0:
-; SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
-; SSE-NEXT:    fstpl -{{[0-9]+}}(%rsp)
-; SSE-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
-; SSE-NEXT:    retq
+; FASTSDAG-SSE-LABEL: fptrunc_x86_fp80_to_double:
+; FASTSDAG-SSE:       # %bb.0:
+; FASTSDAG-SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    fstpl -{{[0-9]+}}(%rsp)
+; FASTSDAG-SSE-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
+; FASTSDAG-SSE-NEXT:    retq
 ;
-; AVX-LABEL: fptrunc_x86_fp80_to_double:
-; AVX:       # %bb.0:
-; AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
-; AVX-NEXT:    fstpl -{{[0-9]+}}(%rsp)
-; AVX-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT:    retq
+; FASTSDAG-AVX-LABEL: fptrunc_x86_fp80_to_double:
+; FASTSDAG-AVX:       # %bb.0:
+; FASTSDAG-AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    fstpl -{{[0-9]+}}(%rsp)
+; FASTSDAG-AVX-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
+; FASTSDAG-AVX-NEXT:    retq
+;
+; GLOBAL-SSE-LABEL: fptrunc_x86_fp80_to_double:
+; GLOBAL-SSE:       # %bb.0:
+; GLOBAL-SSE-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    fstpl -{{[0-9]+}}(%rsp)
+; GLOBAL-SSE-NEXT:    movq -{{[0-9]+}}(%rsp), %rax
+; GLOBAL-SSE-NEXT:    movq %rax, %xmm0
+; GLOBAL-SSE-NEXT:    retq
+;
+; GLOBAL-AVX-LABEL: fptrunc_x86_fp80_to_double:
+; GLOBAL-AVX:       # %bb.0:
+; GLOBAL-AVX-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    fstpl -{{[0-9]+}}(%rsp)
+; GLOBAL-AVX-NEXT:    movq -{{[0-9]+}}(%rsp), %rax
+; GLOBAL-AVX-NEXT:    vmovq %rax, %xmm0
+; GLOBAL-AVX-NEXT:    retq
   %1 = fptrunc x86_fp80 %x to double
   ret double %1
 }
@@ -166,12 +274,6 @@ define double @fptrunc_x86_fp80_to_double(x86_fp80 %x) {
 ; FAST-AVX: {{.*}}
 ; FAST-SSE: {{.*}}
 ; FAST-X86: {{.*}}
-; FASTSDAG-AVX: {{.*}}
-; FASTSDAG-SSE: {{.*}}
-; FASTSDAG-X86: {{.*}}
-; GLOBAL-AVX: {{.*}}
-; GLOBAL-SSE: {{.*}}
-; GLOBAL-X86: {{.*}}
 ; SDAG-AVX: {{.*}}
 ; SDAG-SSE: {{.*}}
 ; SDAG-X86: {{.*}}

>From 80998165bbd4f2d12444ce89c5238d260bac45b3 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Thu, 25 Sep 2025 18:05:47 -0700
Subject: [PATCH 3/6] Generalize FPTRUNC/FPEXT lowering using mem

---
 .../llvm/CodeGen/GlobalISel/LegalizerHelper.h |  1 +
 .../llvm/CodeGen/GlobalISel/LegalizerInfo.h   |  6 ++++
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    | 31 ++++++++++++++++-
 .../lib/Target/X86/GISel/X86LegalizerInfo.cpp | 34 ++-----------------
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.h  |  3 --
 5 files changed, 39 insertions(+), 36 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 22569aab236af..690f40c51fdd2 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -483,6 +483,7 @@ class LegalizerHelper {
   LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI);
   LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI);
 
+  LLVM_ABI LegalizeResult lowerFPExtAndTruncMem(MachineInstr &MI);
   LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI);
   LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI);
   LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI);
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index fd72a3898562e..836e87de6f62d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -742,6 +742,12 @@ class LegalizeRuleSet {
   LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
     return actionFor(LegalizeAction::Lower, Types);
   }
+  LegalizeRuleSet &lowerFor(bool Pred,
+                            std::initializer_list<std::pair<LLT, LLT>> Types) {
+    if (!Pred)
+      return *this;
+    return actionFor(LegalizeAction::Lower, Types);
+  }
   /// The instruction is lowered when type indexes 0 and 1 is any type pair in
   /// the given list.
   LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types,
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index f3e036ed1b947..86ca857f92f24 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4667,6 +4667,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
   case G_FPTOUI_SAT:
   case G_FPTOSI_SAT:
     return lowerFPTOINT_SAT(MI);
+  case G_FPEXT:
+    return lowerFPExtAndTruncMem(MI);
   case G_FPTRUNC:
     return lowerFPTRUNC(MI);
   case G_FPOWI:
@@ -8408,6 +8410,33 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
   return Legalized;
 }
 
+// fp conversions using truncating and extending loads and stores.
+LegalizerHelper::LegalizeResult
+LegalizerHelper::lowerFPExtAndTruncMem(MachineInstr &MI) {
+  assert((MI.getOpcode() == TargetOpcode::G_FPEXT ||
+          MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
+         "Only G_FPEXT and G_FPTRUNC are expected");
+
+  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
+  MachinePointerInfo PtrInfo;
+  LLT StackTy = MI.getOpcode() == TargetOpcode::G_FPEXT ? SrcTy : DstTy;
+  Align StackTyAlign = getStackTemporaryAlignment(StackTy);
+  auto StackTemp =
+      createStackTemporary(StackTy.getSizeInBytes(), StackTyAlign, PtrInfo);
+
+  MachineFunction &MF = MIRBuilder.getMF();
+  auto *StoreMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
+                                           StackTy, StackTyAlign);
+  MIRBuilder.buildStore(SrcReg, StackTemp, *StoreMMO);
+
+  auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
+                                          StackTy, StackTyAlign);
+  MIRBuilder.buildLoad(DstReg, StackTemp, *LoadMMO);
+
+  MI.eraseFromParent();
+  return Legalized;
+}
+
 // f64 -> f16 conversion using round-to-nearest-even rounding mode.
 LegalizerHelper::LegalizeResult
 LegalizerHelper::lowerFPTRUNC_F64_TO_F16(MachineInstr &MI) {
@@ -8533,7 +8562,7 @@ LegalizerHelper::lowerFPTRUNC(MachineInstr &MI) {
   if (DstTy.getScalarType() == S16 && SrcTy.getScalarType() == S64)
     return lowerFPTRUNC_F64_TO_F16(MI);
 
-  return UnableToLegalize;
+  return lowerFPExtAndTruncMem(MI);
 }
 
 LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPOWI(MachineInstr &MI) {
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 128ffbf7e49c3..e9bc5834ea69c 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -447,13 +447,13 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
       .legalFor(HasSSE2, {{s64, s32}})
       .legalFor(HasAVX, {{v4s64, v4s32}})
       .legalFor(HasAVX512, {{v8s64, v8s32}})
-      .customFor(UseX87, {{s64, s32}, {s80, s32}, {s80, s64}});
+      .lowerFor(UseX87, {{s64, s32}, {s80, s32}, {s80, s64}});
 
   getActionDefinitionsBuilder(G_FPTRUNC)
       .legalFor(HasSSE2, {{s32, s64}})
       .legalFor(HasAVX, {{v4s32, v4s64}})
       .legalFor(HasAVX512, {{v8s32, v8s64}})
-      .customFor(UseX87, {{s32, s64}, {s32, s80}, {s64, s80}});
+      .lowerFor(UseX87, {{s32, s64}, {s32, s80}, {s64, s80}});
 
   getActionDefinitionsBuilder(G_SITOFP)
       .legalFor(HasSSE1, {{s32, s32}})
@@ -623,9 +623,6 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
     return legalizeSITOFP(MI, MRI, Helper);
   case TargetOpcode::G_FPTOSI:
     return legalizeFPTOSI(MI, MRI, Helper);
-  case TargetOpcode::G_FPEXT:
-  case TargetOpcode::G_FPTRUNC:
-    return legalizeFPExtAndTrunc(MI, MRI, Helper);
   case TargetOpcode::G_GET_ROUNDING:
     return legalizeGETROUNDING(MI, MRI, Helper);
   }
@@ -870,33 +867,6 @@ bool X86LegalizerInfo::legalizeGETROUNDING(MachineInstr &MI,
   return true;
 }
 
-bool X86LegalizerInfo::legalizeFPExtAndTrunc(MachineInstr &MI,
-                                             MachineRegisterInfo &MRI,
-                                             LegalizerHelper &Helper) const {
-  assert((MI.getOpcode() == TargetOpcode::G_FPEXT ||
-          MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
-         "Only G_FPEXT and G_FPTRUNC are expected");
-  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
-  MachinePointerInfo PtrInfo;
-  LLT StackTy = MI.getOpcode() == TargetOpcode::G_FPEXT ? SrcTy : DstTy;
-  Align StackTyAlign = Helper.getStackTemporaryAlignment(StackTy);
-  auto StackTemp = Helper.createStackTemporary(StackTy.getSizeInBytes(),
-                                               StackTyAlign, PtrInfo);
-
-  MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
-  MachineFunction &MF = MIRBuilder.getMF();
-  auto *StoreMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
-                                           StackTy, StackTyAlign);
-  MIRBuilder.buildStore(SrcReg, StackTemp, *StoreMMO);
-
-  auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
-                                          StackTy, StackTyAlign);
-  MIRBuilder.buildLoad(DstReg, StackTemp, *LoadMMO);
-
-  MI.eraseFromParent();
-  return true;
-}
-
 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
                                          MachineInstr &MI) const {
   return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 7c00531d371e7..0003552d70ee0 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -57,9 +57,6 @@ class X86LegalizerInfo : public LegalizerInfo {
 
   bool legalizeGETROUNDING(MachineInstr &MI, MachineRegisterInfo &MRI,
                            LegalizerHelper &Helper) const;
-
-  bool legalizeFPExtAndTrunc(MachineInstr &MI, MachineRegisterInfo &MRI,
-                             LegalizerHelper &Helper) const;
 };
 } // namespace llvm
 #endif

>From 86ce2c00b23771f1c63db7995cfbcbd90941b037 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sat, 20 Dec 2025 02:46:54 +0100
Subject: [PATCH 4/6] Wording for FP

Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
 llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index fdfeb1a5ec5b2..652b066099de8 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -8502,7 +8502,7 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
   return Legalized;
 }
 
-// fp conversions using truncating and extending loads and stores.
+// Floating-point conversions using truncating and extending loads and stores.
 LegalizerHelper::LegalizeResult
 LegalizerHelper::lowerFPExtAndTruncMem(MachineInstr &MI) {
   assert((MI.getOpcode() == TargetOpcode::G_FPEXT ||

>From 1c16d73b582d2d6a269af0c75390d2927421a5cc Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sun, 11 Jan 2026 05:48:23 -0800
Subject: [PATCH 5/6] Support G_FPEXTLOAD and G_FPTRUNCSTORE

---
 llvm/docs/GlobalISel/GenericOpcode.rst        |  30 ++++
 .../CodeGen/GlobalISel/GenericMachineInstrs.h |  48 ++++++-
 .../llvm/CodeGen/GlobalISel/LegalizerInfo.h   |   9 ++
 .../CodeGen/GlobalISel/MachineIRBuilder.h     |  13 ++
 llvm/include/llvm/Support/TargetOpcodes.def   |   6 +
 llvm/include/llvm/Target/GenericOpcodes.td    |  18 +++
 .../Target/GlobalISel/SelectionDAGCompat.td   |  12 +-
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    |  57 +++++++-
 .../CodeGen/GlobalISel/MachineIRBuilder.cpp   |  14 ++
 llvm/lib/CodeGen/GlobalISel/Utils.cpp         |   2 +
 llvm/lib/CodeGen/MachineVerifier.cpp          |  13 +-
 .../lib/Target/X86/GISel/X86LegalizerInfo.cpp |  14 +-
 .../Target/X86/GISel/X86RegisterBankInfo.cpp  |   2 +
 .../GlobalISel/legalizer-info-validation.mir  |   7 +-
 .../Inputs/reference_x86_vocab_print.txt      |   2 +
 .../reference_x86_vocab_wo=0.5_print.txt      |   2 +
 .../GlobalISel/legalizer-info-validation.mir  |   7 +-
 llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll   |  54 ++++---
 .../test/MachineVerifier/test_g_fpextload.mir |  28 ++++
 .../MachineVerifier/test_g_fptruncstore.mir   |  32 +++++
 .../match-table-cxx.td                        | 132 +++++++++---------
 .../GlobalISelEmitter/GlobalISelEmitter.td    |   2 +-
 llvm/test/TableGen/RegClassByHwMode.td        |  28 ++--
 llvm/utils/TableGen/GlobalISelEmitter.cpp     |  14 ++
 24 files changed, 410 insertions(+), 136 deletions(-)
 create mode 100644 llvm/test/MachineVerifier/test_g_fpextload.mir
 create mode 100644 llvm/test/MachineVerifier/test_g_fptruncstore.mir

diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst
index 329d9d13ebddd..35a8df99bcfde 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.rst
+++ b/llvm/docs/GlobalISel/GenericOpcode.rst
@@ -919,6 +919,21 @@ Unlike in SelectionDAG, atomic loads are expressed with the same
 opcodes as regular loads. G_LOAD, G_SEXTLOAD and G_ZEXTLOAD may all
 have atomic memory operands.
 
+G_FPEXTLOAD
+^^^^^^^^^^^
+
+Generic floating-point extending load. Expects a MachineMemOperand in addition
+to explicit operands. Loads a floating-point value from memory and extends it
+to a larger floating-point type.
+
+The memory size must be smaller than the result type. For example, loading an
+f32 value from memory and extending it to f64, or loading an f16 value and
+extending it to f32.
+
+.. code-block:: none
+
+  %1:_(s64) = G_FPEXTLOAD %0:_(p0) :: (load (s32))
+
 G_INDEXED_LOAD
 ^^^^^^^^^^^^^^
 
@@ -945,6 +960,21 @@ the high bits are implicitly truncated. If this is a vector store, the
 high elements are discarded (i.e. this does not function as a per-lane
 vector, truncating store)
 
+G_FPTRUNCSTORE
+^^^^^^^^^^^^^^
+
+Generic floating-point truncating store. Expects a MachineMemOperand in
+addition to explicit operands. Truncates a floating-point value to a smaller
+floating-point type and stores it to memory.
+
+The memory size must be smaller than the source value type. For example,
+truncating an f64 value to f32 and storing it, or truncating an f32 value
+to f16 and storing it.
+
+.. code-block:: none
+
+  G_FPTRUNCSTORE %0:_(s64), %1:_(p0) :: (store (s32))
+
 G_INDEXED_STORE
 ^^^^^^^^^^^^^^^
 
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 5faf57fd06228..e708d399bc25f 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -80,7 +80,7 @@ class GMemOperation : public GenericMachineInstr {
 };
 
 /// Represents any type of generic load or store.
-/// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD.
+/// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD, G_FPEXTLOAD, G_FPTRUNCSTORE.
 class GLoadStore : public GMemOperation {
 public:
   /// Get the source register of the pointer value.
@@ -92,6 +92,8 @@ class GLoadStore : public GMemOperation {
     case TargetOpcode::G_STORE:
     case TargetOpcode::G_ZEXTLOAD:
     case TargetOpcode::G_SEXTLOAD:
+    case TargetOpcode::G_FPEXTLOAD:
+    case TargetOpcode::G_FPTRUNCSTORE:
       return true;
     default:
       return false;
@@ -145,7 +147,7 @@ class GIndexedAnyExtLoad : public GIndexedLoad {
   }
 };
 
-/// Represents a G_ZEXTLOAD.
+/// Represents a G_INDEXED_ZEXTLOAD.
 class GIndexedZExtLoad : GIndexedExtLoad {
 public:
   static bool classof(const MachineInstr *MI) {
@@ -153,7 +155,7 @@ class GIndexedZExtLoad : GIndexedExtLoad {
   }
 };
 
-/// Represents a G_SEXTLOAD.
+/// Represents a G_INDEXED_SEXTLOAD.
 class GIndexedSExtLoad : GIndexedExtLoad {
 public:
   static bool classof(const MachineInstr *MI) {
@@ -197,6 +199,7 @@ class GAnyLoad : public GLoadStore {
     case TargetOpcode::G_LOAD:
     case TargetOpcode::G_ZEXTLOAD:
     case TargetOpcode::G_SEXTLOAD:
+    case TargetOpcode::G_FPEXTLOAD:
       return true;
     default:
       return false;
@@ -212,12 +215,13 @@ class GLoad : public GAnyLoad {
   }
 };
 
-/// Represents either a G_SEXTLOAD or G_ZEXTLOAD.
+/// Represents either a G_SEXTLOAD, G_ZEXTLOAD, or G_FPEXTLOAD.
 class GExtLoad : public GAnyLoad {
 public:
   static bool classof(const MachineInstr *MI) {
     return MI->getOpcode() == TargetOpcode::G_SEXTLOAD ||
-           MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
+           MI->getOpcode() == TargetOpcode::G_ZEXTLOAD ||
+           MI->getOpcode() == TargetOpcode::G_FPEXTLOAD;
   }
 };
 
@@ -237,17 +241,47 @@ class GZExtLoad : public GExtLoad {
   }
 };
 
-/// Represents a G_STORE.
-class GStore : public GLoadStore {
+/// Represents a G_FPEXTLOAD.
+class GFPExtLoad : public GAnyLoad {
+public:
+  static bool classof(const MachineInstr *MI) {
+    return MI->getOpcode() == TargetOpcode::G_FPEXTLOAD;
+  }
+};
+
+/// Represents any generic store, including truncating variants.
+class GAnyStore : public GLoadStore {
 public:
   /// Get the stored value register.
   Register getValueReg() const { return getOperand(0).getReg(); }
 
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    case TargetOpcode::G_STORE:
+    case TargetOpcode::G_FPTRUNCSTORE:
+      return true;
+    default:
+      return false;
+    }
+  }
+};
+
+/// Represents a G_STORE.
+class GStore : public GAnyStore {
+public:
   static bool classof(const MachineInstr *MI) {
     return MI->getOpcode() == TargetOpcode::G_STORE;
   }
 };
 
+/// Represents a G_FPTRUNCSTORE.
+class GFPTruncStore : public GAnyStore {
+public:
+  static bool classof(const MachineInstr *MI) {
+    return MI->getOpcode() == TargetOpcode::G_FPTRUNCSTORE;
+  }
+};
+
 /// Represents a G_UNMERGE_VALUES.
 class GUnmerge : public GenericMachineInstr {
 public:
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index 41d59d6fd567a..b27cde8fd31cc 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -680,6 +680,15 @@ class LegalizeRuleSet {
                     LegalityPredicates::typePairAndMemDescInSet(
                         typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc));
   }
+  LegalizeRuleSet &legalForTypesWithMemDesc(
+      bool Pred, std::initializer_list<LegalityPredicates::TypePairAndMemDesc>
+                     TypesAndMemDesc) {
+    if (!Pred)
+      return *this;
+    return actionIf(LegalizeAction::Legal,
+                    LegalityPredicates::typePairAndMemDescInSet(
+                        typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc));
+  }
   /// The instruction is legal when type indexes 0 and 1 are both in the given
   /// list. That is, the type pair is in the cartesian product of the list.
   LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 5f3f1d386569c..30cc5a7d6fbf5 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1083,6 +1083,19 @@ class LLVM_ABI MachineIRBuilder {
   MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr,
                                  MachineMemOperand &MMO);
 
+  /// Build and insert `<opcode> Val, Addr, MMO`.
+  ///
+  /// Stores the value \p Val to \p Addr.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Val must be a generic virtual register.
+  /// \pre \p Addr must be a generic virtual register with pointer type.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildStoreInstr(unsigned Opcode, const SrcOp &Val,
+                                      const SrcOp &Addr,
+                                      MachineMemOperand &MMO);
+
   /// Build and insert a G_STORE instruction, while constructing the
   /// MachineMemOperand.
   MachineInstrBuilder
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 0d92f50a09d38..d20c66417ffcd 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -409,6 +409,9 @@ HANDLE_TARGET_OPCODE(G_SEXTLOAD)
 /// Generic zeroext load
 HANDLE_TARGET_OPCODE(G_ZEXTLOAD)
 
+/// Generic floating-point extending load
+HANDLE_TARGET_OPCODE(G_FPEXTLOAD)
+
 /// Generic indexed load (including anyext load)
 HANDLE_TARGET_OPCODE(G_INDEXED_LOAD)
 
@@ -421,6 +424,9 @@ HANDLE_TARGET_OPCODE(G_INDEXED_ZEXTLOAD)
 /// Generic store.
 HANDLE_TARGET_OPCODE(G_STORE)
 
+/// Generic floating-point truncating store
+HANDLE_TARGET_OPCODE(G_FPTRUNCSTORE)
+
 /// Generic indexed store.
 HANDLE_TARGET_OPCODE(G_INDEXED_STORE)
 
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 1b65b8b73527d..5c85a41beae24 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1346,6 +1346,15 @@ def G_ZEXTLOAD : GenericInstruction {
   let mayLoad = true;
 }
 
+// Generic floating-point extending load. Expects a MachineMemOperand in
+// addition to explicit operands.
+def G_FPEXTLOAD : GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins ptype1:$addr);
+  let hasSideEffects = false;
+  let mayLoad = true;
+}
+
 // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
 // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
 //  then the value is loaded from $newaddr.
@@ -1380,6 +1389,15 @@ def G_STORE : GenericInstruction {
   let mayStore = true;
 }
 
+// Generic floating-point truncating store. Expects a MachineMemOperand in
+// addition to explicit operands.
+def G_FPTRUNCSTORE : GenericInstruction {
+  let OutOperandList = (outs);
+  let InOperandList = (ins type0:$src, ptype1:$addr);
+  let hasSideEffects = false;
+  let mayStore = true;
+}
+
 // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
 def G_INDEXED_STORE : GenericInstruction {
   let OutOperandList = (outs ptype0:$newaddr);
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index a69e089779315..917a29db7448b 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -35,6 +35,11 @@ class GINodeEquiv<Instruction i, SDNode node> {
   // depending on the predicates on the node.
   Instruction IfSignExtend = ?;
   Instruction IfZeroExtend = ?;
+  // In contrast to SelectionDAG we would like not to overload an anyext load
+  // for floating point truncation and extending stores and loads. Instead we
+  // assign separate opcodes for it.
+  Instruction IfFPExtend = ?;
+  Instruction IfFPTrunc = ?;
 
   // SelectionDAG has one setcc for all compares. This differentiates
   // for G_ICMP and G_FCMP.
@@ -235,6 +240,7 @@ def : GINodeEquiv<G_LOAD, ld> {
   let CheckMMOIsNonAtomic = true;
   let IfSignExtend = G_SEXTLOAD;
   let IfZeroExtend = G_ZEXTLOAD;
+  let IfFPExtend = G_FPEXTLOAD;
 }
 
 def : GINodeEquiv<G_ICMP, setcc> {
@@ -248,7 +254,11 @@ def : GINodeEquiv<G_ICMP, setcc> {
 // G_STORE handles both atomic and non-atomic stores where as SelectionDAG had
 // separate nodes for them. This GINodeEquiv maps the non-atomic stores to
 // G_STORE with a non-atomic MachineMemOperand.
-def : GINodeEquiv<G_STORE, st> { let CheckMMOIsNonAtomic = true; }
+def : GINodeEquiv<G_STORE, st> {
+  let CheckMMOIsNonAtomic = true;
+  let IfFPTrunc = G_FPTRUNCSTORE;
+}
+
 def : GINodeEquiv<G_STORE, atomic_store> {
   let CheckMMOIsNonAtomic = false;
   let CheckMMOIsAtomic = true;
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 42ae035758930..dd48ba80a7e8f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1687,7 +1687,8 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
     return reduceLoadStoreWidth(LoadMI, TypeIdx, NarrowTy);
   }
   case TargetOpcode::G_ZEXTLOAD:
-  case TargetOpcode::G_SEXTLOAD: {
+  case TargetOpcode::G_SEXTLOAD:
+  case TargetOpcode::G_FPEXTLOAD: {
     auto &LoadMI = cast<GExtLoad>(MI);
     Register DstReg = LoadMI.getDstReg();
     Register PtrReg = LoadMI.getPointerReg();
@@ -1707,8 +1708,10 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
 
     if (isa<GZExtLoad>(LoadMI))
       MIRBuilder.buildZExt(DstReg, TmpReg);
-    else
+    else if (isa<GSExtLoad>(LoadMI))
       MIRBuilder.buildSExt(DstReg, TmpReg);
+    else
+      MIRBuilder.buildFPExt(DstReg, TmpReg);
 
     LoadMI.eraseFromParent();
     return Legalized;
@@ -1737,6 +1740,30 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
 
     return reduceLoadStoreWidth(StoreMI, 0, NarrowTy);
   }
+  case TargetOpcode::G_FPTRUNCSTORE: {
+    auto &StoreMI = cast<GFPTruncStore>(MI);
+    Register SrcReg = StoreMI.getValueReg();
+    Register PtrReg = StoreMI.getPointerReg();
+
+    auto &MMO = StoreMI.getMMO();
+    unsigned MemSize = MMO.getSizeInBits().getValue();
+    if (MemSize > NarrowSize) {
+      return UnableToLegalize;
+    }
+
+    auto TmpReg = MIRBuilder.buildFPTrunc(NarrowTy, SrcReg).getReg(0);
+    if (MemSize == NarrowSize) {
+      MIRBuilder.buildStore(TmpReg, PtrReg, MMO);
+    } else if (MemSize < NarrowSize) {
+      MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNCSTORE)
+          .addUse(TmpReg)
+          .addUse(PtrReg)
+          .addMemOperand(&MMO);
+    }
+
+    StoreMI.eraseFromParent();
+    return Legalized;
+  }
   case TargetOpcode::G_SELECT:
     return narrowScalarSelect(MI, TypeIdx, NarrowTy);
   case TargetOpcode::G_AND:
@@ -3147,6 +3174,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
   case TargetOpcode::G_LOAD:
   case TargetOpcode::G_SEXTLOAD:
   case TargetOpcode::G_ZEXTLOAD:
+  case TargetOpcode::G_FPEXTLOAD:
     Observer.changingInstr(MI);
     widenScalarDst(MI, WideTy);
     Observer.changedInstr(MI);
@@ -3180,6 +3208,13 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
     Observer.changedInstr(MI);
     return Legalized;
   }
+  case TargetOpcode::G_FPTRUNCSTORE:
+    if (TypeIdx != 0)
+      return UnableToLegalize;
+    Observer.changingInstr(MI);
+    widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_FPEXT);
+    Observer.changedInstr(MI);
+    return Legalized;
   case TargetOpcode::G_CONSTANT: {
     MachineOperand &SrcMO = MI.getOperand(1);
     LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
@@ -8517,7 +8552,19 @@ LegalizerHelper::lowerFPExtAndTruncMem(MachineInstr &MI) {
 
   auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
   MachinePointerInfo PtrInfo;
-  LLT StackTy = MI.getOpcode() == TargetOpcode::G_FPEXT ? SrcTy : DstTy;
+  unsigned StoreOpc;
+  unsigned LoadOpc;
+  LLT StackTy;
+  if (MI.getOpcode() == TargetOpcode::G_FPEXT) {
+    StackTy = SrcTy;
+    StoreOpc = TargetOpcode::G_STORE;
+    LoadOpc = TargetOpcode::G_FPEXTLOAD;
+  } else {
+    StackTy = DstTy;
+    StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
+    LoadOpc = TargetOpcode::G_LOAD;
+  }
+
   Align StackTyAlign = getStackTemporaryAlignment(StackTy);
   auto StackTemp =
       createStackTemporary(StackTy.getSizeInBytes(), StackTyAlign, PtrInfo);
@@ -8525,11 +8572,11 @@ LegalizerHelper::lowerFPExtAndTruncMem(MachineInstr &MI) {
   MachineFunction &MF = MIRBuilder.getMF();
   auto *StoreMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
                                            StackTy, StackTyAlign);
-  MIRBuilder.buildStore(SrcReg, StackTemp, *StoreMMO);
+  MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
 
   auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
                                           StackTy, StackTyAlign);
-  MIRBuilder.buildLoad(DstReg, StackTemp, *LoadMMO);
+  MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
 
   MI.eraseFromParent();
   return Legalized;
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 3906b311addf0..7e2f582779f5f 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -500,6 +500,20 @@ MachineInstrBuilder MachineIRBuilder::buildStore(const SrcOp &Val,
   return MIB;
 }
 
+MachineInstrBuilder MachineIRBuilder::buildStoreInstr(unsigned Opcode,
+                                                      const SrcOp &Val,
+                                                      const SrcOp &Addr,
+                                                      MachineMemOperand &MMO) {
+  assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
+  assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
+
+  auto MIB = buildInstr(Opcode);
+  Val.addSrcToMIB(MIB);
+  Addr.addSrcToMIB(MIB);
+  MIB.addMemOperand(&MMO);
+  return MIB;
+}
+
 MachineInstrBuilder
 MachineIRBuilder::buildStore(const SrcOp &Val, const SrcOp &Addr,
                              MachinePointerInfo PtrInfo, Align Alignment,
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 35e89cae9e929..c9c30b0601f3a 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1777,8 +1777,10 @@ bool llvm::isPreISelGenericFloatingPointOpcode(unsigned Opc) {
   case TargetOpcode::G_FNEARBYINT:
   case TargetOpcode::G_FNEG:
   case TargetOpcode::G_FPEXT:
+  case TargetOpcode::G_FPEXTLOAD:
   case TargetOpcode::G_FPOW:
   case TargetOpcode::G_FPTRUNC:
+  case TargetOpcode::G_FPTRUNCSTORE:
   case TargetOpcode::G_FREM:
   case TargetOpcode::G_FRINT:
   case TargetOpcode::G_FSIN:
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 5ce7606b051a5..d1d402ae042af 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1254,7 +1254,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
   case TargetOpcode::G_LOAD:
   case TargetOpcode::G_STORE:
   case TargetOpcode::G_ZEXTLOAD:
-  case TargetOpcode::G_SEXTLOAD: {
+  case TargetOpcode::G_SEXTLOAD:
+  case TargetOpcode::G_FPEXTLOAD:
+  case TargetOpcode::G_FPTRUNCSTORE: {
     LLT ValTy = MRI->getType(MI->getOperand(0).getReg());
     LLT PtrTy = MRI->getType(MI->getOperand(1).getReg());
     if (!PtrTy.isPointer())
@@ -1267,11 +1269,14 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
              MI);
     } else {
       const MachineMemOperand &MMO = **MI->memoperands_begin();
-      if (MI->getOpcode() == TargetOpcode::G_ZEXTLOAD ||
-          MI->getOpcode() == TargetOpcode::G_SEXTLOAD) {
+      if (isa<GExtLoad>(*MI)) {
         if (TypeSize::isKnownGE(MMO.getSizeInBits().getValue(),
                                 ValTy.getSizeInBits()))
           report("Generic extload must have a narrower memory type", MI);
+      } else if (isa<GFPTruncStore>(*MI)) {
+        if (TypeSize::isKnownGE(MMO.getSizeInBits().getValue(),
+                                ValTy.getSizeInBits()))
+          report("Generic truncstore must have a narrower memory type", MI);
       } else if (MI->getOpcode() == TargetOpcode::G_LOAD) {
         if (TypeSize::isKnownGT(MMO.getSize().getValue(),
                                 ValTy.getSizeInBytes()))
@@ -1296,7 +1301,7 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
       }
 
       const AtomicOrdering Order = MMO.getSuccessOrdering();
-      if (Opc == TargetOpcode::G_STORE) {
+      if (isa<GAnyStore>(*MI)) {
         if (Order == AtomicOrdering::Acquire ||
             Order == AtomicOrdering::AcquireRelease)
           report("atomic store cannot use acquire ordering", MI);
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 8890952fac2c6..845341ec26e47 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -339,15 +339,9 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
     Action.legalForTypesWithMemDesc({{s8, p0, s8, 1},
                                      {s16, p0, s16, 1},
                                      {s32, p0, s32, 1},
+                                     {s80, p0, s80, 1},
                                      {p0, p0, p0, 1},
                                      {v4s8, p0, v4s8, 1}});
-
-    if (UseX87)
-      Action.legalForTypesWithMemDesc({{s80, p0, s32, 1},
-                                       {s80, p0, s64, 1},
-                                       {s32, p0, s80, 1},
-                                       {s64, p0, s80, 1},
-                                       {s80, p0, s80, 1}});
     if (Is64Bit)
       Action.legalForTypesWithMemDesc(
           {{s64, p0, s64, 1}, {v2s32, p0, v2s32, 1}});
@@ -400,6 +394,12 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
     // TODO - SSE41/AVX2/AVX512F/AVX512BW vector extensions
   }
 
+  for (unsigned Op : {G_FPEXTLOAD, G_FPTRUNCSTORE}) {
+    auto &Action = getActionDefinitionsBuilder(Op);
+    Action.legalForTypesWithMemDesc(
+        UseX87, {{s80, p0, s32, 1}, {s80, p0, s64, 1}, {s64, p0, s32, 1}});
+  }
+
   // sext, zext, and anyext
   getActionDefinitionsBuilder(G_ANYEXT)
       .legalFor({s8, s16, s32, s128})
diff --git a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
index b23d791501729..f6b64fdc7269c 100644
--- a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp
@@ -294,6 +294,8 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
   case TargetOpcode::G_FPEXT:
   case TargetOpcode::G_FPTRUNC:
   case TargetOpcode::G_FCONSTANT:
+  case TargetOpcode::G_FPEXTLOAD:
+  case TargetOpcode::G_FPTRUNCSTORE:
     // Instruction having only floating-point operands (all scalars in
     // VECRReg)
     getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 8a0071c9ea5c1..1cfdc70aa80e5 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -1,4 +1,3 @@
-# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -mtriple=aarch64-- -run-pass=legalizer %s \
 # RUN:     -mcpu=cortex-a75 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
 
@@ -214,6 +213,9 @@
 # DEBUG-NEXT: G_ZEXTLOAD (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_FPEXTLOAD (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: G_INDEXED_LOAD (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
@@ -227,6 +229,9 @@
 # DEBUG-NEXT: G_STORE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_FPTRUNCSTORE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: G_INDEXED_STORE (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt
index 62e07445ad12e..cbceaeb5fc5f6 100644
--- a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt
+++ b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt
@@ -417,6 +417,7 @@ Key: G_FNEARBYINT:  [ 0.00  0.00 ]
 Key: G_FNEG:  [ 0.00  0.00 ]
 Key: G_FNSTCW:  [ 0.00  0.00 ]
 Key: G_FPEXT:  [ 0.00  0.00 ]
+Key: G_FPEXTLOAD:  [ 0.00  0.00 ]
 Key: G_FPOW:  [ 0.00  0.00 ]
 Key: G_FPOWI:  [ 0.00  0.00 ]
 Key: G_FPTOSI:  [ 0.00  0.00 ]
@@ -424,6 +425,7 @@ Key: G_FPTOSI_SAT:  [ 0.00  0.00 ]
 Key: G_FPTOUI:  [ 0.00  0.00 ]
 Key: G_FPTOUI_SAT:  [ 0.00  0.00 ]
 Key: G_FPTRUNC:  [ 0.00  0.00 ]
+Key: G_FPTRUNCSTORE:  [ 0.00  0.00 ]
 Key: G_FRAME_INDEX:  [ 0.00  0.00 ]
 Key: G_FREEZE:  [ 0.00  0.00 ]
 Key: G_FREM:  [ 0.00  0.00 ]
diff --git a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt
index 03a3fafc6b801..aa7561a31bf4a 100644
--- a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt
+++ b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt
@@ -417,6 +417,7 @@ Key: G_FNEARBYINT:  [ 0.00  0.00 ]
 Key: G_FNEG:  [ 0.00  0.00 ]
 Key: G_FNSTCW:  [ 0.00  0.00 ]
 Key: G_FPEXT:  [ 0.00  0.00 ]
+Key: G_FPEXTLOAD:  [ 0.00  0.00 ]
 Key: G_FPOW:  [ 0.00  0.00 ]
 Key: G_FPOWI:  [ 0.00  0.00 ]
 Key: G_FPTOSI:  [ 0.00  0.00 ]
@@ -424,6 +425,7 @@ Key: G_FPTOSI_SAT:  [ 0.00  0.00 ]
 Key: G_FPTOUI:  [ 0.00  0.00 ]
 Key: G_FPTOUI_SAT:  [ 0.00  0.00 ]
 Key: G_FPTRUNC:  [ 0.00  0.00 ]
+Key: G_FPTRUNCSTORE:  [ 0.00  0.00 ]
 Key: G_FRAME_INDEX:  [ 0.00  0.00 ]
 Key: G_FREEZE:  [ 0.00  0.00 ]
 Key: G_FREM:  [ 0.00  0.00 ]
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index ff8b8faee5c15..8953fb237f94c 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -1,4 +1,3 @@
-# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -mtriple=riscv32-- -run-pass=legalizer %s \
 # RUN:     -mattr=+m,+zbb,+zfh,+v -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
 # RUN: llc -mtriple=riscv64-- -run-pass=legalizer %s \
@@ -214,6 +213,9 @@
 # DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_FPEXTLOAD (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: G_INDEXED_LOAD (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
@@ -226,6 +228,9 @@
 # DEBUG-NEXT: G_STORE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_FPTRUNCSTORE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: G_INDEXED_STORE (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
diff --git a/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll b/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
index 0ad9b90806ce9..c1ba7495e7e2d 100644
--- a/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
+++ b/llvm/test/CodeGen/X86/isel-fptrunc-fpext.ll
@@ -15,10 +15,10 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -fast-isel=0 -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefixes AVX,GLOBAL-AVX
 
 define double @fpext_float_to_double(float %f) {
-; X86-LABEL: fpext_float_to_double:
-; X86:       # %bb.0:
-; X86-NEXT:    flds {{[0-9]+}}(%esp)
-; X86-NEXT:    retl
+; FASTSDAG-X86-LABEL: fpext_float_to_double:
+; FASTSDAG-X86:       # %bb.0:
+; FASTSDAG-X86-NEXT:    flds {{[0-9]+}}(%esp)
+; FASTSDAG-X86-NEXT:    retl
 ;
 ; SSE-LABEL: fpext_float_to_double:
 ; SSE:       # %bb.0:
@@ -29,6 +29,17 @@ define double @fpext_float_to_double(float %f) {
 ; AVX:       # %bb.0:
 ; AVX-NEXT:    vcvtss2sd %xmm0, %xmm0, %xmm0
 ; AVX-NEXT:    retq
+;
+; GLOBAL-X86-LABEL: fpext_float_to_double:
+; GLOBAL-X86:       # %bb.0:
+; GLOBAL-X86-NEXT:    pushl %eax
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 8
+; GLOBAL-X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; GLOBAL-X86-NEXT:    movl %eax, (%esp)
+; GLOBAL-X86-NEXT:    flds (%esp)
+; GLOBAL-X86-NEXT:    popl %eax
+; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 4
+; GLOBAL-X86-NEXT:    retl
   %1 = fpext float %f to double
   ret double %1
 }
@@ -136,16 +147,16 @@ define x86_fp80 @fpext_double_to_x86_fp80(double %d) {
 }
 
 define float @fptrunc_double_to_float(double %d) {
-; FASTSDAG-X86-LABEL: fptrunc_double_to_float:
-; FASTSDAG-X86:       # %bb.0:
-; FASTSDAG-X86-NEXT:    pushl %eax
-; FASTSDAG-X86-NEXT:    .cfi_def_cfa_offset 8
-; FASTSDAG-X86-NEXT:    fldl {{[0-9]+}}(%esp)
-; FASTSDAG-X86-NEXT:    fstps (%esp)
-; FASTSDAG-X86-NEXT:    flds (%esp)
-; FASTSDAG-X86-NEXT:    popl %eax
-; FASTSDAG-X86-NEXT:    .cfi_def_cfa_offset 4
-; FASTSDAG-X86-NEXT:    retl
+; X86-LABEL: fptrunc_double_to_float:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %eax
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    fldl {{[0-9]+}}(%esp)
+; X86-NEXT:    fstps (%esp)
+; X86-NEXT:    flds (%esp)
+; X86-NEXT:    popl %eax
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
 ;
 ; SSE-LABEL: fptrunc_double_to_float:
 ; SSE:       # %bb.0:
@@ -156,21 +167,6 @@ define float @fptrunc_double_to_float(double %d) {
 ; AVX:       # %bb.0:
 ; AVX-NEXT:    vcvtsd2ss %xmm0, %xmm0, %xmm0
 ; AVX-NEXT:    retq
-;
-; GLOBAL-X86-LABEL: fptrunc_double_to_float:
-; GLOBAL-X86:       # %bb.0:
-; GLOBAL-X86-NEXT:    pushl %eax
-; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 8
-; GLOBAL-X86-NEXT:    leal {{[0-9]+}}(%esp), %eax
-; GLOBAL-X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; GLOBAL-X86-NEXT:    movl 4(%eax), %eax
-; GLOBAL-X86-NEXT:    movl %esp, %edx
-; GLOBAL-X86-NEXT:    movl %ecx, (%esp)
-; GLOBAL-X86-NEXT:    movl %eax, 4(%edx)
-; GLOBAL-X86-NEXT:    flds (%esp)
-; GLOBAL-X86-NEXT:    popl %eax
-; GLOBAL-X86-NEXT:    .cfi_def_cfa_offset 4
-; GLOBAL-X86-NEXT:    retl
   %1 = fptrunc double %d to float
   ret float %1
 }
diff --git a/llvm/test/MachineVerifier/test_g_fpextload.mir b/llvm/test/MachineVerifier/test_g_fpextload.mir
new file mode 100644
index 0000000000000..e0e6f08684405
--- /dev/null
+++ b/llvm/test/MachineVerifier/test_g_fpextload.mir
@@ -0,0 +1,28 @@
+# RUN: not --crash llc -o - -mtriple=x86_64-linux-gnu -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: x86-registered-target
+
+---
+name:            test_fpextload
+legalized:       true
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK: Bad machine code: Generic memory instruction must access a pointer
+    %0:_(s64) = G_CONSTANT i64 0
+    %1:_(s32) = G_FPEXTLOAD %0 :: (load (s16))
+
+    ; CHECK: *** Bad machine code: Generic instruction accessing memory must have one mem operand ***
+    %2:_(p0) = G_IMPLICIT_DEF
+    %3:_(s64) = G_FPEXTLOAD %2
+
+    ; CHECK: Bad machine code: Generic extload must have a narrower memory type
+    %4:_(s64) = G_FPEXTLOAD %2 :: (load (s64))
+
+    ; CHECK: Bad machine code: Generic extload must have a narrower memory type
+    %5:_(s64) = G_FPEXTLOAD %2 :: (load (s128))
+
+...
diff --git a/llvm/test/MachineVerifier/test_g_fptruncstore.mir b/llvm/test/MachineVerifier/test_g_fptruncstore.mir
new file mode 100644
index 0000000000000..0c10c20dc4386
--- /dev/null
+++ b/llvm/test/MachineVerifier/test_g_fptruncstore.mir
@@ -0,0 +1,32 @@
+# RUN: not --crash llc -o - -mtriple=x86_64-linux-gnu -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: x86-registered-target
+
+---
+name:            test_fptruncstore
+legalized:       true
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK: Bad machine code: Generic memory instruction must access a pointer
+    %0:_(s64) = G_CONSTANT i64 0
+    %1:_(s32) = G_IMPLICIT_DEF
+    G_FPTRUNCSTORE %1, %0 :: (store (s16))
+
+    ; CHECK: *** Bad machine code: Generic instruction accessing memory must have one mem operand ***
+    %2:_(p0) = G_IMPLICIT_DEF
+    %3:_(s64) = G_IMPLICIT_DEF
+    G_FPTRUNCSTORE %3, %2
+
+    ; CHECK: Bad machine code: Generic truncstore must have a narrower memory type
+    %4:_(s32) = G_IMPLICIT_DEF
+    G_FPTRUNCSTORE %4, %2 :: (store (s32))
+
+    ; CHECK: Bad machine code: Generic truncstore must have a narrower memory type
+    %5:_(s32) = G_IMPLICIT_DEF
+    G_FPTRUNCSTORE %5, %2 :: (store (s64))
+
+...
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
index 28017700a0448..ccd13a86f8ed6 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
@@ -96,71 +96,71 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(105), GIMT_Encode2(217), /*)*//*default:*//*Label 5*/ GIMT_Encode4(524),
-// CHECK-NEXT:      /* 10 */ /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(458), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
-// CHECK-NEXT:      /* 182 */ /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(476), GIMT_Encode4(0),
-// CHECK-NEXT:      /* 190 */ /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4(488), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
-// CHECK-NEXT:      /* 418 */ /*TargetOpcode::G_FNEG*//*Label 3*/ GIMT_Encode4(500), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
-// CHECK-NEXT:      /* 454 */ /*TargetOpcode::G_FABS*//*Label 4*/ GIMT_Encode4(512),
-// CHECK-NEXT:      /* 458 */ // Label 0: @458
-// CHECK-NEXT:      /* 458 */ GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(475), // Rule ID 2 //
-// CHECK-NEXT:      /* 463 */ GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled),
-// CHECK-NEXT:      /* 466 */ // MIs[0] x
-// CHECK-NEXT:      /* 466 */ // No operand predicates
-// CHECK-NEXT:      /* 466 */ // MIs[0] y
-// CHECK-NEXT:      /* 466 */ // No operand predicates
-// CHECK-NEXT:      /* 466 */ GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0),
-// CHECK-NEXT:      /* 470 */ GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1),
-// CHECK-NEXT:      /* 474 */ // Combiner Rule #2: TwoMatchNoApply
-// CHECK-NEXT:      /* 474 */ GIR_EraseRootFromParent_Done,
-// CHECK-NEXT:      /* 475 */ // Label 6: @475
-// CHECK-NEXT:      /* 475 */ GIM_Reject,
-// CHECK-NEXT:      /* 476 */ // Label 1: @476
-// CHECK-NEXT:      /* 476 */ GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(487), // Rule ID 3 //
-// CHECK-NEXT:      /* 481 */ GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled),
-// CHECK-NEXT:      /* 484 */ // MIs[0] a
-// CHECK-NEXT:      /* 484 */ // No operand predicates
-// CHECK-NEXT:      /* 484 */ // MIs[0] y
-// CHECK-NEXT:      /* 484 */ // No operand predicates
-// CHECK-NEXT:      /* 484 */ // Combiner Rule #3: NoMatchTwoApply
-// CHECK-NEXT:      /* 484 */ GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2),
-// CHECK-NEXT:      /* 487 */ // Label 7: @487
-// CHECK-NEXT:      /* 487 */ GIM_Reject,
-// CHECK-NEXT:      /* 488 */ // Label 2: @488
-// CHECK-NEXT:      /* 488 */ GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(499), // Rule ID 4 //
-// CHECK-NEXT:      /* 493 */ GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule4Enabled),
-// CHECK-NEXT:      /* 496 */ // MIs[0] a
-// CHECK-NEXT:      /* 496 */ // No operand predicates
-// CHECK-NEXT:      /* 496 */ // MIs[0] y
-// CHECK-NEXT:      /* 496 */ // No operand predicates
-// CHECK-NEXT:      /* 496 */ // Combiner Rule #4: CombineCXXOrder
-// CHECK-NEXT:      /* 496 */ GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner3),
-// CHECK-NEXT:      /* 499 */ // Label 8: @499
-// CHECK-NEXT:      /* 499 */ GIM_Reject,
-// CHECK-NEXT:      /* 500 */ // Label 3: @500
-// CHECK-NEXT:      /* 500 */ GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(511), // Rule ID 1 //
-// CHECK-NEXT:      /* 505 */ GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
-// CHECK-NEXT:      /* 508 */ // MIs[0] a
-// CHECK-NEXT:      /* 508 */ // No operand predicates
-// CHECK-NEXT:      /* 508 */ // MIs[0] b
-// CHECK-NEXT:      /* 508 */ // No operand predicates
-// CHECK-NEXT:      /* 508 */ // Combiner Rule #1: TwoMatchTwoApply
-// CHECK-NEXT:      /* 508 */ GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1),
-// CHECK-NEXT:      /* 511 */ // Label 9: @511
-// CHECK-NEXT:      /* 511 */ GIM_Reject,
-// CHECK-NEXT:      /* 512 */ // Label 4: @512
-// CHECK-NEXT:      /* 512 */ GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4(523), // Rule ID 0 //
-// CHECK-NEXT:      /* 517 */ GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
-// CHECK-NEXT:      /* 520 */ // MIs[0] a
-// CHECK-NEXT:      /* 520 */ // No operand predicates
-// CHECK-NEXT:      /* 520 */ // MIs[0] b
-// CHECK-NEXT:      /* 520 */ // No operand predicates
-// CHECK-NEXT:      /* 520 */ // Combiner Rule #0: OneMatchOneApply
-// CHECK-NEXT:      /* 520 */ GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
-// CHECK-NEXT:      /* 523 */ // Label 10: @523
-// CHECK-NEXT:      /* 523 */ GIM_Reject,
-// CHECK-NEXT:      /* 524 */ // Label 5: @524
-// CHECK-NEXT:      /* 524 */ GIM_Reject,
-// CHECK-NEXT:      /* 525 */ }; // Size: 525 bytes
+// CHECK-NEXT:      GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2({{[0-9]+}}), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label 5*/ GIMT_Encode4({{[0-9]+}}),
+// CHECK-NEXT:      /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4({{[0-9]+}}), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
+// CHECK-NEXT:      /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4({{[0-9]+}}), GIMT_Encode4(0),
+// CHECK-NEXT:      /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4({{[0-9]+}}), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
+// CHECK-NEXT:      /*TargetOpcode::G_FNEG*//*Label 3*/ GIMT_Encode4({{[0-9]+}}), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
+// CHECK-NEXT:      /*TargetOpcode::G_FABS*//*Label 4*/ GIMT_Encode4({{[0-9]+}}),
+// CHECK-NEXT:      // Label 0: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 2 //
+// CHECK-NEXT:      GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled),
+// CHECK-NEXT:      // MIs[0] x
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // MIs[0] y
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0),
+// CHECK-NEXT:      GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1),
+// CHECK-NEXT:      // Combiner Rule #2: TwoMatchNoApply
+// CHECK-NEXT:      GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:      // Label 6: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Reject,
+// CHECK-NEXT:      // Label 1: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 3 //
+// CHECK-NEXT:      GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled),
+// CHECK-NEXT:      // MIs[0] a
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // MIs[0] y
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // Combiner Rule #3: NoMatchTwoApply
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2),
+// CHECK-NEXT:      // Label 7: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Reject,
+// CHECK-NEXT:      // Label 2: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 4 //
+// CHECK-NEXT:      GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule4Enabled),
+// CHECK-NEXT:      // MIs[0] a
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // MIs[0] y
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // Combiner Rule #4: CombineCXXOrder
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner3),
+// CHECK-NEXT:      // Label 8: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Reject,
+// CHECK-NEXT:      // Label 3: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 1 //
+// CHECK-NEXT:      GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),
+// CHECK-NEXT:      // MIs[0] a
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // MIs[0] b
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // Combiner Rule #1: TwoMatchTwoApply
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1),
+// CHECK-NEXT:      // Label 9: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Reject,
+// CHECK-NEXT:      // Label 4: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 0 //
+// CHECK-NEXT:      GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),
+// CHECK-NEXT:      // MIs[0] a
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // MIs[0] b
+// CHECK-NEXT:      // No operand predicates
+// CHECK-NEXT:      // Combiner Rule #0: OneMatchOneApply
+// CHECK-NEXT:      GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),
+// CHECK-NEXT:      // Label 10: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Reject,
+// CHECK-NEXT:      // Label 5: @{{[0-9]+}}
+// CHECK-NEXT:      GIM_Reject,
+// CHECK-NEXT:      }; // Size: 529 bytes
 // CHECK-NEXT:   return MatchTable0;
 // CHECK-NEXT: }
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index 64ca63da3b6f0..c686e0d1519b0 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -535,7 +535,7 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
 // R00O-NEXT:  GIM_Reject,
 // R00O:       // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
 // R00O-NEXT:  GIM_Reject,
-// R00O-NEXT:  }; // Size: 1918 bytes
+// R00O-NEXT:  }; // Size: 1926 bytes
 
 def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
                  [(set GPR32:$dst,
diff --git a/llvm/test/TableGen/RegClassByHwMode.td b/llvm/test/TableGen/RegClassByHwMode.td
index 0be22be560bea..7022c75fe8b24 100644
--- a/llvm/test/TableGen/RegClassByHwMode.td
+++ b/llvm/test/TableGen/RegClassByHwMode.td
@@ -234,36 +234,36 @@ include "Common/RegClassByHwModeCommon.td"
 
 
 
-// ISEL-GISEL: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(148),
+// ISEL-GISEL: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(152),
 // ISEL-GISEL-NEXT:   GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s64,
 // ISEL-GISEL-NEXT:   GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic,
 // ISEL-GISEL-NEXT:   GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
 // ISEL-GISEL-NEXT:   GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::XRegsRegClassID),
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(101),
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(105),
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
 
 // FIXME: This should be a direct check for regbank, not have an incorrect class
 
 // ISEL-GISEL-NEXT:     GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::PtrRegs32RegClassID),
-// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(85), // Rule ID 1 //
+// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(89), // Rule ID 1 //
 // ISEL-GISEL-NEXT:       GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode1),
 // ISEL-GISEL-NEXT:       // (ld:{ *:[i64] } PtrRegOperand:{ *:[i32] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (MY_LOAD:{ *:[i64] } ?:{ *:[i32] }:$src)
 // ISEL-GISEL-NEXT:       GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::MY_LOAD),
 // ISEL-GISEL-NEXT:       GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:       // GIR_Coverage, 1,
 // ISEL-GISEL-NEXT:       GIR_Done,
-// ISEL-GISEL-NEXT:     // Label 5: @85
-// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(100), // Rule ID 2 //
+// ISEL-GISEL-NEXT:     // Label 5: @89
+// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(104), // Rule ID 2 //
 // ISEL-GISEL-NEXT:       GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode2),
 // ISEL-GISEL-NEXT:       // (ld:{ *:[i64] } PtrRegOperand:{ *:[i32] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (MY_LOAD:{ *:[i64] } ?:{ *:[i32] }:$src)
 // ISEL-GISEL-NEXT:       GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::MY_LOAD),
 // ISEL-GISEL-NEXT:       GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:       // GIR_Coverage, 2,
 // ISEL-GISEL-NEXT:       GIR_Done,
-// ISEL-GISEL-NEXT:     // Label 6: @100
+// ISEL-GISEL-NEXT:     // Label 6: @104
 // ISEL-GISEL-NEXT:     GIM_Reject,
-// ISEL-GISEL-NEXT:   // Label 4: @101
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(124), // Rule ID 3 //
+// ISEL-GISEL-NEXT:   // Label 4: @105
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(128), // Rule ID 3 //
 // ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode0),
 // ISEL-GISEL-NEXT:     // MIs[0] src
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/64,
@@ -273,8 +273,8 @@ include "Common/RegClassByHwModeCommon.td"
 // ISEL-GISEL-NEXT:     GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:     // GIR_Coverage, 3,
 // ISEL-GISEL-NEXT:     GIR_Done,
-// ISEL-GISEL-NEXT:   // Label 7: @124
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(147), // Rule ID 4 //
+// ISEL-GISEL-NEXT:   // Label 7: @128
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(151), // Rule ID 4 //
 // ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode3),
 // ISEL-GISEL-NEXT:     // MIs[0] src
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
@@ -284,12 +284,12 @@ include "Common/RegClassByHwModeCommon.td"
 // ISEL-GISEL-NEXT:     GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:     // GIR_Coverage, 4,
 // ISEL-GISEL-NEXT:     GIR_Done,
-// ISEL-GISEL-NEXT:   // Label 8: @147
+// ISEL-GISEL-NEXT:   // Label 8: @151
 // ISEL-GISEL-NEXT:   GIM_Reject,
-// ISEL-GISEL-NEXT: // Label 3: @148
+// ISEL-GISEL-NEXT: // Label 3: @152
 // ISEL-GISEL-NEXT: GIM_Reject,
-// ISEL-GISEL-NEXT: // Label 1: @149
-// ISEL-GISEL-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(186), // Rule ID 0 //
+// ISEL-GISEL-NEXT: // Label 1: @153
+// ISEL-GISEL-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(190), // Rule ID 0 //
 // ISEL-GISEL-NEXT:   GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode0),
 // ISEL-GISEL-NEXT:   GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s64,
 // ISEL-GISEL-NEXT:   GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic,
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index bd79c423a00e2..447bd4c4a0184 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -541,8 +541,12 @@ GlobalISelEmitter::getEquivNode(const Record &Equiv,
       N.getIntrinsicInfo(CGP)->isConvergent)
     return &Target.getInstruction(Equiv.getValueAsDef("IfConvergent"));
 
+  bool IsAnyExtLoad = false;
+  bool IsTruncStore = false;
   for (const TreePredicateCall &Call : N.getPredicateCalls()) {
     const TreePredicateFn &Predicate = Call.Fn;
+    IsAnyExtLoad |= Predicate.isAnyExtLoad();
+    IsTruncStore |= Predicate.isTruncStore();
     if (!Equiv.isValueUnset("IfSignExtend") &&
         (Predicate.isLoad() || Predicate.isAtomic()) &&
         Predicate.isSignExtLoad())
@@ -551,6 +555,16 @@ GlobalISelEmitter::getEquivNode(const Record &Equiv,
         (Predicate.isLoad() || Predicate.isAtomic()) &&
         Predicate.isZeroExtLoad())
       return &Target.getInstruction(Equiv.getValueAsDef("IfZeroExtend"));
+    if (!Equiv.isValueUnset("IfFPExtend") &&
+        (Predicate.isLoad() || Predicate.isAtomic()) && IsAnyExtLoad &&
+        Predicate.getMemoryVT() != nullptr &&
+        getValueType(Predicate.getMemoryVT()).isFloatingPoint())
+      return &Target.getInstruction(Equiv.getValueAsDef("IfFPExtend"));
+    if (!Equiv.isValueUnset("IfFPTrunc") &&
+        (Predicate.isStore() || Predicate.isAtomic()) && IsTruncStore &&
+        Predicate.getMemoryVT() != nullptr &&
+        getValueType(Predicate.getMemoryVT()).isFloatingPoint())
+      return &Target.getInstruction(Equiv.getValueAsDef("IfFPTrunc"));
   }
 
   return &Target.getInstruction(Equiv.getValueAsDef("I"));

>From d1ec2151d6dfb80dde4048f5fff49521c9f6bbc7 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sun, 11 Jan 2026 08:08:47 -0800
Subject: [PATCH 6/6] Fix RegClassByHwMode.td as well

---
 llvm/test/TableGen/RegClassByHwMode.td | 56 +++++++++++++-------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/llvm/test/TableGen/RegClassByHwMode.td b/llvm/test/TableGen/RegClassByHwMode.td
index 853efd6c8cd1e..d88b501910f6b 100644
--- a/llvm/test/TableGen/RegClassByHwMode.td
+++ b/llvm/test/TableGen/RegClassByHwMode.td
@@ -270,37 +270,37 @@ include "Common/RegClassByHwModeCommon.td"
 
 
 
-// ISEL-GISEL: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(152),
+// ISEL-GISEL: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4({{[0-9]+}}),
 // ISEL-GISEL-NEXT:   GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s64,
 // ISEL-GISEL-NEXT:   GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic,
 // ISEL-GISEL-NEXT:   GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
 // ISEL-GISEL-NEXT:   GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::XRegsRegClassID),
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(105),
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4({{[0-9]+}}),
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
 
 // FIXME: This should be a direct check for regbank, not have an incorrect class
 
 // ISEL-GISEL-NEXT:     GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::PtrRegs32RegClassID),
-// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(89), // Rule ID 1 //
+// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 4 //
 // ISEL-GISEL-NEXT:       GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode0),
 // ISEL-GISEL-NEXT:       // (ld:{ *:[i64] } PtrRegOperand:{ *:[i32] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (MY_LOAD:{ *:[i64] } ?:{ *:[i32] }:$src)
 // ISEL-GISEL-NEXT:       GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::MY_LOAD),
 // ISEL-GISEL-NEXT:       GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:       // GIR_Coverage, 4,
 // ISEL-GISEL-NEXT:       GIR_Done,
-// ISEL-GISEL-NEXT:     // Label 5: @85
-// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(100), // Rule ID 5 //
+// ISEL-GISEL-NEXT:     // Label 5: @{{[0-9]+}}
+// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 5 //
 // ISEL-GISEL-NEXT:       GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode1),
 // ISEL-GISEL-NEXT:       // (ld:{ *:[i64] } PtrRegOperand:{ *:[i32] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>>  =>  (MY_LOAD:{ *:[i64] } ?:{ *:[i32] }:$src)
 // ISEL-GISEL-NEXT:       GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::MY_LOAD),
 // ISEL-GISEL-NEXT:       GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:       // GIR_Coverage, 5,
 // ISEL-GISEL-NEXT:       GIR_Done,
-// ISEL-GISEL-NEXT:     // Label 6: @104
+// ISEL-GISEL-NEXT:     // Label 6: @{{[0-9]+}}
 // ISEL-GISEL-NEXT:     GIM_Reject,
-// ISEL-GISEL-NEXT:   // Label 4: @105
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(128), // Rule ID 3 //
-// ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode0),
+// ISEL-GISEL-NEXT:   // Label 4: @{{[0-9]+}}
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 6 //
+// ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode2),
 // ISEL-GISEL-NEXT:     // MIs[0] src
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/64,
 // ISEL-GISEL-NEXT:     GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::PtrRegs32RegClassID),
@@ -309,8 +309,8 @@ include "Common/RegClassByHwModeCommon.td"
 // ISEL-GISEL-NEXT:     GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:     // GIR_Coverage, 6,
 // ISEL-GISEL-NEXT:     GIR_Done,
-// ISEL-GISEL-NEXT:   // Label 7: @128
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(151), // Rule ID 4 //
+// ISEL-GISEL-NEXT:   // Label 7: @{{[0-9]+}}
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 7 //
 // ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode3),
 // ISEL-GISEL-NEXT:     // MIs[0] src
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
@@ -320,38 +320,38 @@ include "Common/RegClassByHwModeCommon.td"
 // ISEL-GISEL-NEXT:     GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:     // GIR_Coverage, 7,
 // ISEL-GISEL-NEXT:     GIR_Done,
-// ISEL-GISEL-NEXT:   // Label 8: @151
+// ISEL-GISEL-NEXT:   // Label 8: @{{[0-9]+}}
 // ISEL-GISEL-NEXT:   GIM_Reject,
-// ISEL-GISEL-NEXT: // Label 3: @152
+// ISEL-GISEL-NEXT: // Label 3: @{{[0-9]+}}
 // ISEL-GISEL-NEXT: GIM_Reject,
-// ISEL-GISEL-NEXT: // Label 1: @153
-// ISEL-GISEL-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(190),
+// ISEL-GISEL-NEXT: // Label 1: @{{[0-9]+}}
+// ISEL-GISEL-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4({{[0-9]+}}),
 // ISEL-GISEL-NEXT:   GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s64,
 // ISEL-GISEL-NEXT:   GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic,
 // ISEL-GISEL-NEXT:   GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
 // ISEL-GISEL-NEXT:   GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::XRegsRegClassID),
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4(212),
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4({{[0-9]+}}),
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
 // ISEL-GISEL-NEXT:     GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::PtrRegs32RegClassID),
-// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4(196), // Rule ID 0 //
+// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 0 //
 // ISEL-GISEL-NEXT:       GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode0),
 // ISEL-GISEL-NEXT:       // (st XRegs_EvenIfRequired:{ *:[i64] }:$val, MyPtrRC:{ *:[i32] }:$src)<<P:Predicate_unindexedstore>><<P:Predicate_store>>  =>  (MY_STORE XRegs_EvenIfRequired:{ *:[i64] }:$val, ?:{ *:[i32] }:$src)
 // ISEL-GISEL-NEXT:       GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::MY_STORE),
 // ISEL-GISEL-NEXT:       GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:       // GIR_Coverage, 0,
 // ISEL-GISEL-NEXT:       GIR_Done,
-// ISEL-GISEL-NEXT:     // Label 11: @196
-// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4(211), // Rule ID 1 //
+// ISEL-GISEL-NEXT:     // Label 11: @{{[0-9]+}}
+// ISEL-GISEL-NEXT:     GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 1 //
 // ISEL-GISEL-NEXT:       GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode1),
 // ISEL-GISEL-NEXT:       // (st XRegs_EvenIfRequired:{ *:[i64] }:$val, MyPtrRC:{ *:[i32] }:$src)<<P:Predicate_unindexedstore>><<P:Predicate_store>>  =>  (MY_STORE XRegs_EvenIfRequired:{ *:[i64] }:$val, ?:{ *:[i32] }:$src)
 // ISEL-GISEL-NEXT:       GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::MY_STORE),
 // ISEL-GISEL-NEXT:       GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:       // GIR_Coverage, 1,
 // ISEL-GISEL-NEXT:       GIR_Done,
-// ISEL-GISEL-NEXT:     // Label 12: @211
+// ISEL-GISEL-NEXT:     // Label 12: @{{[0-9]+}}
 // ISEL-GISEL-NEXT:     GIM_Reject,
-// ISEL-GISEL-NEXT:   // Label 10: @212
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4(235), // Rule ID 2 //
+// ISEL-GISEL-NEXT:   // Label 10: @{{[0-9]+}}
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 2 //
 // ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode2),
 // ISEL-GISEL-NEXT:     // MIs[0] src
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/64,
@@ -361,8 +361,8 @@ include "Common/RegClassByHwModeCommon.td"
 // ISEL-GISEL-NEXT:     GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:     // GIR_Coverage, 2,
 // ISEL-GISEL-NEXT:     GIR_Done,
-// ISEL-GISEL-NEXT:   // Label 13: @235
-// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4(258), // Rule ID 3 //
+// ISEL-GISEL-NEXT:   // Label 13: @{{[0-9]+}}
+// ISEL-GISEL-NEXT:   GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4({{[0-9]+}}), // Rule ID 3 //
 // ISEL-GISEL-NEXT:     GIM_CheckFeatures, GIMT_Encode2(GIFBS_HwMode3),
 // ISEL-GISEL-NEXT:     // MIs[0] src
 // ISEL-GISEL-NEXT:     GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
@@ -372,13 +372,13 @@ include "Common/RegClassByHwModeCommon.td"
 // ISEL-GISEL-NEXT:     GIR_RootConstrainSelectedInstOperands,
 // ISEL-GISEL-NEXT:     // GIR_Coverage, 3,
 // ISEL-GISEL-NEXT:   GIR_Done,
-// ISEL-GISEL-NEXT:   // Label 14: @258
+// ISEL-GISEL-NEXT:   // Label 14: @{{[0-9]+}}
 // ISEL-GISEL-NEXT:   GIM_Reject,
-// ISEL-GISEL-NEXT: // Label 9: @259
+// ISEL-GISEL-NEXT: // Label 9: @{{[0-9]+}}
 // ISEL-GISEL-NEXT: GIM_Reject,
-// ISEL-GISEL-NEXT: // Label 2: @260
+// ISEL-GISEL-NEXT: // Label 2: @{{[0-9]+}}
 // ISEL-GISEL-NEXT: GIM_Reject,
-// ISEL-GISEL-NEXT: }; // Size: 261 bytes
+// ISEL-GISEL-NEXT: }; // Size: 265 bytes
 
 def HasAlignedRegisters : Predicate<"Subtarget->hasAlignedRegisters()">;
 def HasUnalignedRegisters : Predicate<"Subtarget->hasUnalignedRegisters()">;



More information about the llvm-commits mailing list