[llvm-branch-commits] [llvm] 3273cda - [GlobalISel][AArch64] Do not remove dst type predicates from pattern children nodes. (#221576)

Tobias Hieta via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Sep 25 01:23:55 PDT 2026


Author: David Green
Date: 2026-09-25T10:23:25+02:00
New Revision: 3273cdaa5ea1188a6dc630039f0be90d8d8084b6

URL: https://github.com/llvm/llvm-project/commit/3273cdaa5ea1188a6dc630039f0be90d8d8084b6
DIFF: https://github.com/llvm/llvm-project/commit/3273cdaa5ea1188a6dc630039f0be90d8d8084b6.diff

LOG: [GlobalISel][AArch64] Do not remove dst type predicates from pattern children nodes. (#221576)

Given an instruction with a non-concrete type (G_CONCAT_VECTOR), with a
child pattern instruction with a concrete type (G_FPTRUNC), the concrete
type check for the child would incorrectly be removed. This patch makes
sure they remain. This makes the match table a little larger, but many
should be able to be optimized away (providing that the two operands
with the same type can be matched up).

Fixes #221458

(cherry picked from commit 09be00c800cf9ae03a2c8fbdc215c259ac39f30f)

Added: 
    llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerTypes.td

Modified: 
    llvm/test/CodeGen/AArch64/fptrunc.ll
    llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/CodeGen/AArch64/fptrunc.ll b/llvm/test/CodeGen/AArch64/fptrunc.ll
index 56b20eaac1c80e..1e968eeea3d31b 100644
--- a/llvm/test/CodeGen/AArch64/fptrunc.ll
+++ b/llvm/test/CodeGen/AArch64/fptrunc.ll
@@ -2,6 +2,7 @@
 ; RUN: llc -mtriple=aarch64 -global-isel=0 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc -mtriple=aarch64 -global-isel=1 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 ; RUN: llc -mtriple=aarch64 -global-isel=1 -mattr=+fullfp16,+bf16 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc -mtriple=aarch64 -global-isel=1 -mattr=+bf16 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define float @fptrunc_f64_f32(double %a) {
 ; CHECK-LABEL: fptrunc_f64_f32:

diff  --git a/llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerTypes.td b/llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerTypes.td
new file mode 100644
index 00000000000000..ed264b02be1df2
--- /dev/null
+++ b/llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerTypes.td
@@ -0,0 +1,63 @@
+// RUN: llvm-tblgen %s -gen-global-isel -gisel-extended-llt -optimize-match-table=true -I %p/../../../include -I %p/../Common | FileCheck %s
+
+include "llvm/Target/Target.td"
+include "GlobalISelEmitterCommon.td"
+
+// Check the MatchTable does not remove necessary type checks
+
+def V1 : Register<"v1"> { let Namespace = "MyTarget"; }
+def FPR64  : RegisterClass<"MyTarget", [v4f16, v4bf16], 64, (add V1)>;
+def FPR128 : RegisterClass<"MyTarget", [v4f32, v8f16, v8bf16], 128, (add V1)>;
+def BF16I  : I<(outs FPR128:$dst), (ins FPR64:$Rn, FPR128:$Rm), []>;
+def F16I   : I<(outs FPR128:$dst), (ins FPR64:$Rn, FPR128:$Rm), []>;
+
+def : Pat<(v8bf16 (concat_vectors (v4bf16 FPR64:$Rn), (v4bf16 (fpround (v4f32 FPR128:$Rm))))),
+          (BF16I $Rn, $Rm)>;
+def : Pat<(v8f16 (concat_vectors (v4f16 FPR64:$Rn), (v4f16 (fpround (v4f32 FPR128:$Rm))))),
+          (F16I $Rn, $Rm)>;
+
+// CHECK:      constexpr static uint8_t MatchTable0[] = {
+// CHECK-NEXT:   /*   0 */ GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(112),
+// CHECK-NEXT:   /*   5 */   GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_CONCAT_VECTORS),
+// CHECK-NEXT:   /*   9 */   GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
+// CHECK-NEXT:   /*  12 */   GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_v8s16,
+// CHECK-NEXT:   /*  15 */   GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_v4s16,
+// CHECK-NEXT:   /*  18 */   GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_v4s16,
+// CHECK-NEXT:   /*  21 */   GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::FPR128RegClassID),
+// CHECK-NEXT:   /*  25 */   GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::FPR64RegClassID),
+// CHECK-NEXT:   /*  29 */   GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(70), // Rule ID 0 //
+// CHECK-NEXT:   /*  34 */     GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2, // MIs[1]
+// CHECK-NEXT:   /*  38 */     GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_FPTRUNC),
+// CHECK-NEXT:   /*  42 */     GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_v4bf16,
+// CHECK-NEXT:   /*  46 */     GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_v4f32,
+// CHECK-NEXT:   /*  50 */     GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::FPR128RegClassID),
+// CHECK-NEXT:   /*  55 */     GIM_CheckIsSafeToFold, /*NumInsns*/1,
+// CHECK-NEXT:   /*  57 */     // (concat_vectors:{ *:[v8bf16] } FPR64:{ *:[v4bf16] }:$Rn, (fpround:{ *:[v4bf16] } FPR128:{ *:[v4f32] }:$Rm))  =>  (BF16I:{ *:[v8bf16] } ?:{ *:[v4bf16] }:$Rn, ?:{ *:[v4f32] }:$Rm)
+// CHECK-NEXT:   /*  57 */     GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::BF16I),
+// CHECK-NEXT:   /*  60 */     GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
+// CHECK-NEXT:   /*  62 */     GIR_RootToRootCopy, /*OpIdx*/1, // Rn
+// CHECK-NEXT:   /*  64 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // Rm
+// CHECK-NEXT:   /*  68 */     GIR_RootConstrainSelectedInstOperands,
+// CHECK-NEXT:   /*  69 */     // GIR_Coverage, 0,
+// CHECK-NEXT:   /*  69 */     GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:   /*  70 */   // Label 1: @70
+// CHECK-NEXT:   /*  70 */   GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(111), // Rule ID 1 //
+// CHECK-NEXT:   /*  75 */     GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2, // MIs[1]
+// CHECK-NEXT:   /*  79 */     GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_FPTRUNC),
+// CHECK-NEXT:   /*  83 */     GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_v4f16,
+// CHECK-NEXT:   /*  87 */     GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_v4f32,
+// CHECK-NEXT:   /*  91 */     GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::FPR128RegClassID),
+// CHECK-NEXT:   /*  96 */     GIM_CheckIsSafeToFold, /*NumInsns*/1,
+// CHECK-NEXT:   /*  98 */     // (concat_vectors:{ *:[v8f16] } FPR64:{ *:[v4f16] }:$Rn, (fpround:{ *:[v4f16] } FPR128:{ *:[v4f32] }:$Rm))  =>  (F16I:{ *:[v8f16] } ?:{ *:[v4f16] }:$Rn, ?:{ *:[v4f32] }:$Rm)
+// CHECK-NEXT:   /*  98 */     GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::F16I),
+// CHECK-NEXT:   /* 101 */     GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst]
+// CHECK-NEXT:   /* 103 */     GIR_RootToRootCopy, /*OpIdx*/1, // Rn
+// CHECK-NEXT:   /* 105 */     GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // Rm
+// CHECK-NEXT:   /* 109 */     GIR_RootConstrainSelectedInstOperands,
+// CHECK-NEXT:   /* 110 */     // GIR_Coverage, 1,
+// CHECK-NEXT:   /* 110 */     GIR_EraseRootFromParent_Done,
+// CHECK-NEXT:   /* 111 */   // Label 2: @111
+// CHECK-NEXT:   /* 111 */   GIM_Reject,
+// CHECK-NEXT:   /* 112 */ // Label 0: @112
+// CHECK-NEXT:   /* 112 */ GIM_Reject,
+// CHECK-NEXT:   /* 113 */ }; // Size: 113 bytes

diff  --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
index 7f22cbfc7f58dd..531f9c2703bfa6 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
@@ -1621,8 +1621,16 @@ void InstructionMatcher::optimize() {
 
   if (InsnVarID > 0) {
     assert(!Operands.empty() && "Nested instruction is expected to def a vreg");
-    for (auto &OP : Operands[0]->predicates())
+    for (auto &OP : Operands[0]->predicates()) {
+      // LLTOperandMatcher need to be kept as they may have a more specific type
+      // than the parent instruction type.
+      if (const auto *LLTPred = dyn_cast<LLTOperandMatcher>(&*OP)) {
+        if (!LLTPred->getTy().get().isAnyScalar() &&
+            !LLTPred->getTy().get().isAnyVector())
+          continue;
+      }
       OP.reset();
+    }
     Operands[0]->eraseNullPredicates();
   }
   for (auto &OM : Operands) {


        


More information about the llvm-branch-commits mailing list