https://github.com/Pierre-vh updated https://github.com/llvm/llvm-project/pull/197143
>From 13960994418b0079bb70bc6a5b1e7fec3c84c86f Mon Sep 17 00:00:00 2001 From: pvanhout <[email protected]> Date: Tue, 12 May 2026 11:08:12 +0200 Subject: [PATCH 1/3] [GlobalISel] Recursively Optimise MatchTable Matchers The core of this change is the additional call to `Matcher::optimize()` in the `optimizeRules` function, which enables the match table optimization logic to recurse on the children of every GroupMatcher, forming additional groups (which hoist more common predicates into a shared group). To enable that, I had to update the `getFirstConditionAsRootType` implementation to support `GroupMatcher`. I also included a small refactoring of the match table optimization pipeline that was identical between the GlobalISel and GlobalISelCombiner emitters. The results of this change are up to a 25% size reduction for GlobalISel match tables. There is a tiny increase (a few bytes) in a combiner table because we now create new groups (which need up to 3 additional opcodes because of the new `Try` and `Reject` required) to hoist one predicate for only 2 rules, which result in a small net negative change (one or two more ops). I used a small bash script to compare all relevant files, this is the before/after: ``` FILE OLD NEW DIFF% SAME? ---- ------- ------- ----- ----- AArch64GenGlobalISel.inc 202434 192045 -5,1% no AArch64GenPostLegalizeGICombiner.inc 4428 4432 0,1% no AArch64GenPreLegalizeGICombiner.inc 8974 8977 0,0% no AMDGPUGenGlobalISel.inc 789379 590082 -25,2% no AMDGPUGenPostLegalizeGICombiner.inc 9203 9207 0,0% no AMDGPUGenPreLegalizeGICombiner.inc 8950 8954 0,0% no AMDGPUGenRegBankGICombiner.inc 1981 1981 0,0% yes ``` --- .../GlobalISel/preselect-process-phis.mir | 3 + .../select-intrinsic-aarch64-sdiv.mir | 18 ++ .../MatchTableOptimizerRecursion.td | 204 ++++++++++++++++++ .../GlobalISel/GlobalISelMatchTable.cpp | 86 ++++++-- .../Common/GlobalISel/GlobalISelMatchTable.h | 19 +- .../TableGen/GlobalISelCombinerEmitter.cpp | 35 +-- llvm/utils/TableGen/GlobalISelEmitter.cpp | 39 +--- 7 files changed, 310 insertions(+), 94 deletions(-) create mode 100644 llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerRecursion.td diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir b/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir index d59ffff8e5629..9c9ae861fd8e3 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir @@ -1,5 +1,8 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -verify-machineinstrs -mtriple aarch64--- --run-pass=instruction-select -global-isel-abort=1 %s -o - | FileCheck %s + +# XFAIL: * + --- name: test_loop_phi_fpr_to_gpr alignment: 4 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir index 2dc8c9d4772df..82b5eff9b66a0 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir @@ -1,6 +1,24 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s +# XFAIL: * + +# MatchTable Before: +# /* 268430 */ GIM_Try, /*On fail goto*//*Label 4045*/ GIMT_Encode4(268475), // Rule ID 4220 // +# /* 268435 */ GIM_CheckNumOperands, /*MI*/0, /*Expected*/4, +# /* 268438 */ GIM_CheckIntrinsicID, /*MI*/0, /*Op*/1, GIMT_Encode2(Intrinsic::aarch64_sdiv), +# /* 268443 */ GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_i32, +# /* 268446 */ GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_i32, +# /* 268449 */ GIM_RootCheckType, /*Op*/3, /*Type*/GILLT_i32, +# +# MatchTable After: +# /* 241275 */ GIM_SwitchType, /*MI*/0, /*Op*/0, /*[*/GIMT_Encode2(7), GIMT_Encode2(9), /*)*//*default:*//*Label 6365*/ GIMT_Encode4(241364), +# /* 241286 */ /*GILLT_i32*//*Label 6363*/ GIMT_Encode4(241294), +# /* 241290 */ /*GILLT_i64*//*Label 6364*/ GIMT_Encode4(241329), +# +# Matching fails because type is S32 (index 2), but switch wants i32 (index 7). + + --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerRecursion.td b/llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerRecursion.td new file mode 100644 index 0000000000000..0beda69a843c4 --- /dev/null +++ b/llvm/test/TableGen/GlobalISelEmitter/MatchTableOptimizerRecursion.td @@ -0,0 +1,204 @@ +// RUN: llvm-tblgen %s -gen-global-isel -optimize-match-table=true -I %p/../../../include -I %p/../Common | FileCheck %s + +include "llvm/Target/Target.td" +include "GlobalISelEmitterCommon.td" + +// Check the MatchTable recursively optimizes to maximize group formation. + +def InstFourOperands : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4), []>; + +def S0 : Register<"s0"> { let Namespace = "MyTarget"; } +def S1 : Register<"s1"> { let Namespace = "MyTarget"; } +def Z0 : Register<"s1"> { let Namespace = "MyTarget"; } +def Z1 : Register<"s1"> { let Namespace = "MyTarget"; } + +def GPR8_A : RegisterClass<"MyTarget", [i8], 8, (add Z0)>; +def LOAD8_A : I<(outs GPR8_A:$dst), (ins GPR8_A:$src), []>; +def LOAD8Imm_A : I<(outs GPR8_A:$dst), (ins GPR8_A:$src), []>; + +def GPR8_B : RegisterClass<"MyTarget", [i8], 8, (add Z1)>; +def LOAD8_B : I<(outs GPR8_B:$dst), (ins GPR8_B:$src), []>; +def LOAD8Imm_B : I<(outs GPR8_B:$dst), (ins GPR8_B:$src), []>; + +def GPR16_A : RegisterClass<"MyTarget", [i16], 16, (add S0)>; +def LOAD16_A : I<(outs GPR16_A:$dst), (ins GPR16_A:$src), []>; +def LOAD16Imm_A : I<(outs GPR16_A:$dst), (ins GPR16_A:$src), []>; + +def GPR16_B : RegisterClass<"MyTarget", [i16], 16, (add S0)>; +def LOAD16_B : I<(outs GPR16_B:$dst), (ins GPR16_B:$src), []>; +def LOAD16Imm_B : I<(outs GPR16_B:$dst), (ins GPR16_B:$src), []>; + + +def : Pat<(i8 (load GPR8_A:$src)), + (LOAD8_A GPR8_A:$src)>; +def : Pat<(i8 (load GPR8_B:$src)), + (LOAD8_B GPR8_B:$src)>; + +def : Pat<(i8 (load (add GPR8_A:$src, 10))), + (LOAD8Imm_A GPR8_A:$src)>; +def : Pat<(i8 (load (add GPR8_B:$src, 10))), + (LOAD8Imm_B GPR8_B:$src)>; + +def : Pat<(i16 (load GPR16_A:$src)), + (LOAD16_A GPR16_A:$src)>; +def : Pat<(i16 (load GPR16_B:$src)), + (LOAD16_B GPR16_B:$src)>; + +def : Pat<(i16 (load (add GPR16_A:$src, 10))), + (LOAD16Imm_A GPR16_A:$src)>; +def : Pat<(i16 (load (add GPR16_B:$src, 10))), + (LOAD16Imm_B GPR16_B:$src)>; + + +// CHECK: const uint8_t *MyTargetInstructionSelector::getMatchTable() const { +// CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { +// CHECK-NEXT: /* 0 */ GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(377), +// CHECK-NEXT: /* 5 */ GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_LOAD), +// CHECK-NEXT: /* 9 */ GIM_SwitchType, /*MI*/0, /*Op*/0, /*[*/GIMT_Encode2(0), GIMT_Encode2(2), /*)*//*default:*//*Label 3*/ GIMT_Encode4(376), +// CHECK-NEXT: /* 20 */ /*GILLT_s8*//*Label 1*/ GIMT_Encode4(28), +// CHECK-NEXT: /* 24 */ /*GILLT_s16*//*Label 2*/ GIMT_Encode4(202), +// CHECK-NEXT: /* 28 */ // Label 1: @28 +// CHECK-NEXT: /* 28 */ GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(201), +// CHECK-NEXT: /* 33 */ GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic, +// CHECK-NEXT: /* 36 */ GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0, +// CHECK-NEXT: /* 40 */ GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(96), // Rule ID 2 // +// CHECK-NEXT: /* 45 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR8_ARegClassID), +// CHECK-NEXT: /* 49 */ // MIs[0] Operand 1 +// CHECK-NEXT: /* 49 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/8, +// CHECK-NEXT: /* 53 */ GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1] +// CHECK-NEXT: /* 57 */ GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ADD), +// CHECK-NEXT: /* 61 */ GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s8, +// CHECK-NEXT: /* 65 */ GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s8, +// CHECK-NEXT: /* 69 */ GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR8_ARegClassID), +// CHECK-NEXT: /* 74 */ GIM_CheckConstantInt8, /*MI*/1, /*Op*/2, 10, +// CHECK-NEXT: /* 78 */ GIM_CheckIsSafeToFold, /*NumInsns*/1, +// CHECK-NEXT: /* 80 */ // (ld:{ *:[i8] } (add:{ *:[i8] } GPR8_A:{ *:[i8] }:$src, 10:{ *:[i8] }))<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD8Imm_A:{ *:[i8] } GPR8_A:{ *:[i8] }:$src) +// CHECK-NEXT: /* 80 */ GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::LOAD8Imm_A), +// CHECK-NEXT: /* 83 */ GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst] +// CHECK-NEXT: /* 85 */ GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src +// CHECK-NEXT: /* 89 */ GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1, +// CHECK-NEXT: /* 94 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 95 */ // GIR_Coverage, 2, +// CHECK-NEXT: /* 95 */ GIR_EraseRootFromParent_Done, +// CHECK-NEXT: /* 96 */ // Label 5: @96 +// CHECK-NEXT: /* 96 */ GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(152), // Rule ID 3 // +// CHECK-NEXT: /* 101 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR8_BRegClassID), +// CHECK-NEXT: /* 105 */ // MIs[0] Operand 1 +// CHECK-NEXT: /* 105 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/8, +// CHECK-NEXT: /* 109 */ GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1] +// CHECK-NEXT: /* 113 */ GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ADD), +// CHECK-NEXT: /* 117 */ GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s8, +// CHECK-NEXT: /* 121 */ GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s8, +// CHECK-NEXT: /* 125 */ GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR8_BRegClassID), +// CHECK-NEXT: /* 130 */ GIM_CheckConstantInt8, /*MI*/1, /*Op*/2, 10, +// CHECK-NEXT: /* 134 */ GIM_CheckIsSafeToFold, /*NumInsns*/1, +// CHECK-NEXT: /* 136 */ // (ld:{ *:[i8] } (add:{ *:[i8] } GPR8_B:{ *:[i8] }:$src, 10:{ *:[i8] }))<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD8Imm_B:{ *:[i8] } GPR8_B:{ *:[i8] }:$src) +// CHECK-NEXT: /* 136 */ GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::LOAD8Imm_B), +// CHECK-NEXT: /* 139 */ GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst] +// CHECK-NEXT: /* 141 */ GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src +// CHECK-NEXT: /* 145 */ GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1, +// CHECK-NEXT: /* 150 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 151 */ // GIR_Coverage, 3, +// CHECK-NEXT: /* 151 */ GIR_EraseRootFromParent_Done, +// CHECK-NEXT: /* 152 */ // Label 6: @152 +// CHECK-NEXT: /* 152 */ GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(176), // Rule ID 0 // +// CHECK-NEXT: /* 157 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR8_ARegClassID), +// CHECK-NEXT: /* 161 */ // MIs[0] src +// CHECK-NEXT: /* 161 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/8, +// CHECK-NEXT: /* 165 */ GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR8_ARegClassID), +// CHECK-NEXT: /* 169 */ // (ld:{ *:[i8] } GPR8_A:{ *:[i8] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD8_A:{ *:[i8] } GPR8_A:{ *:[i8] }:$src) +// CHECK-NEXT: /* 169 */ GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::LOAD8_A), +// CHECK-NEXT: /* 174 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 175 */ // GIR_Coverage, 0, +// CHECK-NEXT: /* 175 */ GIR_Done, +// CHECK-NEXT: /* 176 */ // Label 7: @176 +// CHECK-NEXT: /* 176 */ GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(200), // Rule ID 1 // +// CHECK-NEXT: /* 181 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR8_BRegClassID), +// CHECK-NEXT: /* 185 */ // MIs[0] src +// CHECK-NEXT: /* 185 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/8, +// CHECK-NEXT: /* 189 */ GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR8_BRegClassID), +// CHECK-NEXT: /* 193 */ // (ld:{ *:[i8] } GPR8_B:{ *:[i8] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD8_B:{ *:[i8] } GPR8_B:{ *:[i8] }:$src) +// CHECK-NEXT: /* 193 */ GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::LOAD8_B), +// CHECK-NEXT: /* 198 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 199 */ // GIR_Coverage, 1, +// CHECK-NEXT: /* 199 */ GIR_Done, +// CHECK-NEXT: /* 200 */ // Label 8: @200 +// CHECK-NEXT: /* 200 */ GIM_Reject, +// CHECK-NEXT: /* 201 */ // Label 4: @201 +// CHECK-NEXT: /* 201 */ GIM_Reject, +// CHECK-NEXT: /* 202 */ // Label 2: @202 +// CHECK-NEXT: /* 202 */ GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(375), +// CHECK-NEXT: /* 207 */ GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(uint8_t)AtomicOrdering::NotAtomic, +// CHECK-NEXT: /* 210 */ GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0, +// CHECK-NEXT: /* 214 */ GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4(270), // Rule ID 6 // +// CHECK-NEXT: /* 219 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR16_ARegClassID), +// CHECK-NEXT: /* 223 */ // MIs[0] Operand 1 +// CHECK-NEXT: /* 223 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/16, +// CHECK-NEXT: /* 227 */ GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1] +// CHECK-NEXT: /* 231 */ GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ADD), +// CHECK-NEXT: /* 235 */ GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s16, +// CHECK-NEXT: /* 239 */ GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s16, +// CHECK-NEXT: /* 243 */ GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR16_ARegClassID), +// CHECK-NEXT: /* 248 */ GIM_CheckConstantInt8, /*MI*/1, /*Op*/2, 10, +// CHECK-NEXT: /* 252 */ GIM_CheckIsSafeToFold, /*NumInsns*/1, +// CHECK-NEXT: /* 254 */ // (ld:{ *:[i16] } (add:{ *:[i16] } GPR16_A:{ *:[i16] }:$src, 10:{ *:[i16] }))<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD16Imm_A:{ *:[i16] } GPR16_A:{ *:[i16] }:$src) +// CHECK-NEXT: /* 254 */ GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::LOAD16Imm_A), +// CHECK-NEXT: /* 257 */ GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst] +// CHECK-NEXT: /* 259 */ GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src +// CHECK-NEXT: /* 263 */ GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1, +// CHECK-NEXT: /* 268 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 269 */ // GIR_Coverage, 6, +// CHECK-NEXT: /* 269 */ GIR_EraseRootFromParent_Done, +// CHECK-NEXT: /* 270 */ // Label 10: @270 +// CHECK-NEXT: /* 270 */ GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4(326), // Rule ID 7 // +// CHECK-NEXT: /* 275 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR16_BRegClassID), +// CHECK-NEXT: /* 279 */ // MIs[0] Operand 1 +// CHECK-NEXT: /* 279 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/16, +// CHECK-NEXT: /* 283 */ GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1] +// CHECK-NEXT: /* 287 */ GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ADD), +// CHECK-NEXT: /* 291 */ GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s16, +// CHECK-NEXT: /* 295 */ GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s16, +// CHECK-NEXT: /* 299 */ GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR16_BRegClassID), +// CHECK-NEXT: /* 304 */ GIM_CheckConstantInt8, /*MI*/1, /*Op*/2, 10, +// CHECK-NEXT: /* 308 */ GIM_CheckIsSafeToFold, /*NumInsns*/1, +// CHECK-NEXT: /* 310 */ // (ld:{ *:[i16] } (add:{ *:[i16] } GPR16_B:{ *:[i16] }:$src, 10:{ *:[i16] }))<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD16Imm_B:{ *:[i16] } GPR16_B:{ *:[i16] }:$src) +// CHECK-NEXT: /* 310 */ GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::LOAD16Imm_B), +// CHECK-NEXT: /* 313 */ GIR_RootToRootCopy, /*OpIdx*/0, // DstI[dst] +// CHECK-NEXT: /* 315 */ GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src +// CHECK-NEXT: /* 319 */ GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1, +// CHECK-NEXT: /* 324 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 325 */ // GIR_Coverage, 7, +// CHECK-NEXT: /* 325 */ GIR_EraseRootFromParent_Done, +// CHECK-NEXT: /* 326 */ // Label 11: @326 +// CHECK-NEXT: /* 326 */ GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4(350), // Rule ID 4 // +// CHECK-NEXT: /* 331 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR16_ARegClassID), +// CHECK-NEXT: /* 335 */ // MIs[0] src +// CHECK-NEXT: /* 335 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/16, +// CHECK-NEXT: /* 339 */ GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR16_ARegClassID), +// CHECK-NEXT: /* 343 */ // (ld:{ *:[i16] } GPR16_A:{ *:[i16] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD16_A:{ *:[i16] } GPR16_A:{ *:[i16] }:$src) +// CHECK-NEXT: /* 343 */ GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::LOAD16_A), +// CHECK-NEXT: /* 348 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 349 */ // GIR_Coverage, 4, +// CHECK-NEXT: /* 349 */ GIR_Done, +// CHECK-NEXT: /* 350 */ // Label 12: @350 +// CHECK-NEXT: /* 350 */ GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4(374), // Rule ID 5 // +// CHECK-NEXT: /* 355 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR16_BRegClassID), +// CHECK-NEXT: /* 359 */ // MIs[0] src +// CHECK-NEXT: /* 359 */ GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/16, +// CHECK-NEXT: /* 363 */ GIM_RootCheckRegBankForClass, /*Op*/1, /*RC*/GIMT_Encode2(MyTarget::GPR16_BRegClassID), +// CHECK-NEXT: /* 367 */ // (ld:{ *:[i16] } GPR16_B:{ *:[i16] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD16_B:{ *:[i16] } GPR16_B:{ *:[i16] }:$src) +// CHECK-NEXT: /* 367 */ GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::LOAD16_B), +// CHECK-NEXT: /* 372 */ GIR_RootConstrainSelectedInstOperands, +// CHECK-NEXT: /* 373 */ // GIR_Coverage, 5, +// CHECK-NEXT: /* 373 */ GIR_Done, +// CHECK-NEXT: /* 374 */ // Label 13: @374 +// CHECK-NEXT: /* 374 */ GIM_Reject, +// CHECK-NEXT: /* 375 */ // Label 9: @375 +// CHECK-NEXT: /* 375 */ GIM_Reject, +// CHECK-NEXT: /* 376 */ // Label 3: @376 +// CHECK-NEXT: /* 376 */ GIM_Reject, +// CHECK-NEXT: /* 377 */ // Label 0: @377 +// CHECK-NEXT: /* 377 */ GIM_Reject, +// CHECK-NEXT: /* 378 */ }; // Size: 378 bytes +// CHECK-NEXT: return MatchTable0; +// CHECK-NEXT: } diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index ab20eb6e2f790..d34388839e4a3 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -93,10 +93,11 @@ llvm::gi::getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset, } template <class GroupT> -std::vector<Matcher *> -llvm::gi::optimizeRules(ArrayRef<Matcher *> Rules, - std::vector<std::unique_ptr<Matcher>> &MatcherStorage) { +static std::vector<Matcher *> +optimizeRules(ArrayRef<Matcher *> Rules, + std::vector<std::unique_ptr<Matcher>> &MatcherStorage) { + std::vector<Matcher *> Worklist(Rules.begin(), Rules.end()); std::vector<Matcher *> OptRules; std::unique_ptr<GroupT> CurrentGroup = std::make_unique<GroupT>(); assert(CurrentGroup->empty() && "Newly created group isn't empty!"); @@ -114,13 +115,15 @@ llvm::gi::optimizeRules(ArrayRef<Matcher *> Rules, append_range(OptRules, CurrentGroup->matchers()); else { CurrentGroup->finalize(); + CurrentGroup->optimize(); OptRules.push_back(CurrentGroup.get()); MatcherStorage.emplace_back(std::move(CurrentGroup)); ++NumGroups; } CurrentGroup = std::make_unique<GroupT>(); }; - for (Matcher *Rule : Rules) { + + for (Matcher *Rule : Worklist) { // Greedily add as many matchers as possible to the current group: if (CurrentGroup->addMatcher(*Rule)) continue; @@ -136,19 +139,50 @@ llvm::gi::optimizeRules(ArrayRef<Matcher *> Rules, } ProcessCurrentGroup(); + assert(OptRules.size() <= Worklist.size() && "Optimization added rules?"); LLVM_DEBUG(dbgs() << "NumGroups: " << NumGroups << "\n"); (void)NumGroups; assert(CurrentGroup->empty() && "The last group wasn't properly processed"); return OptRules; } -template std::vector<Matcher *> llvm::gi::optimizeRules<GroupMatcher>( - ArrayRef<Matcher *> Rules, - std::vector<std::unique_ptr<Matcher>> &MatcherStorage); +std::vector<Matcher *> llvm::gi::optimizeRuleset( + MutableArrayRef<RuleMatcher> Rules, + std::vector<std::unique_ptr<Matcher>> &MatcherStorage) { + std::vector<Matcher *> InputRules; + InputRules.reserve(Rules.size()); + for (RuleMatcher &Rule : Rules) + InputRules.push_back(&Rule); + + // Now sort the Rules. + unsigned CurrentOrdering = 0; + StringMap<unsigned> OpcodeOrder; + for (RuleMatcher &Rule : Rules) { + const StringRef Opcode = Rule.getOpcode(); + assert(!Opcode.empty() && "Didn't expect an undefined opcode"); + if (OpcodeOrder.try_emplace(Opcode, CurrentOrdering).second) + ++CurrentOrdering; + } + + llvm::stable_sort( + InputRules, [&OpcodeOrder](const Matcher *A, const Matcher *B) { + const auto *L = cast<RuleMatcher>(A); + const auto *R = cast<RuleMatcher>(B); + return std::tuple(OpcodeOrder[L->getOpcode()], + L->insnmatchers_front().getNumOperandMatchers()) < + std::tuple(OpcodeOrder[R->getOpcode()], + R->insnmatchers_front().getNumOperandMatchers()); + }); + + for (Matcher *R : InputRules) + R->optimize(); -template std::vector<Matcher *> llvm::gi::optimizeRules<SwitchMatcher>( - ArrayRef<Matcher *> Rules, - std::vector<std::unique_ptr<Matcher>> &MatcherStorage); + // Then form groups, and switches in that order. + std::vector<Matcher *> OptRules = + optimizeRules<GroupMatcher>(InputRules, MatcherStorage); + OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage); + return OptRules; +} static std::string getEncodedEmitStr(StringRef NamedValue, unsigned NumBytes) { if (NumBytes == 2 || NumBytes == 4 || NumBytes == 8) @@ -603,21 +637,20 @@ void GroupMatcher::emit(MatchTable &Table) { void GroupMatcher::optimize() { // Make sure we only sort by a specific predicate within a range of rules that // all have that predicate checked against a specific value (not a wildcard): + // TODO: Is this even relevant ? Check diffs w/ just using a simple sort + // instead of this. auto F = Matchers.begin(); auto T = F; auto E = Matchers.end(); while (T != E) { while (T != E) { - auto *R = static_cast<RuleMatcher *>(*T); - if (!R->getFirstConditionAsRootType().get().isValid()) + if (!(*T)->getFirstConditionAsRootType().get().isValid()) break; ++T; } std::stable_sort(F, T, [](Matcher *A, Matcher *B) { - auto *L = static_cast<RuleMatcher *>(A); - auto *R = static_cast<RuleMatcher *>(B); - return L->getFirstConditionAsRootType() < - R->getFirstConditionAsRootType(); + return A->getFirstConditionAsRootType() < + B->getFirstConditionAsRootType(); }); if (T != E) F = ++T; @@ -626,6 +659,19 @@ void GroupMatcher::optimize() { Matchers = optimizeRules<SwitchMatcher>(Matchers, MatcherStorage); } +LLTCodeGen GroupMatcher::getFirstConditionAsRootType() const { + if (!hasFirstCondition()) + return {}; + + const PredicateMatcher &PM = *Conditions.front(); + if (const auto *TM = dyn_cast<LLTOperandMatcher>(&PM)) { + if (TM->getInsnVarID() == 0 && TM->getOpIdx() == 0) + return TM->getTy(); + } + + return {}; +} + //===- SwitchMatcher ------------------------------------------------------===// SwitchMatcher::SwitchMatcher() : Matcher(MK_Switch) {} @@ -817,13 +863,15 @@ bool RuleMatcher::recordsOperand() const { return matchersRecordOperand(Matchers); } -LLTCodeGen RuleMatcher::getFirstConditionAsRootType() { +LLTCodeGen RuleMatcher::getFirstConditionAsRootType() const { InstructionMatcher &InsnMatcher = *Matchers.front(); - if (!InsnMatcher.predicates_empty()) + if (!InsnMatcher.predicates_empty()) { if (const auto *TM = - dyn_cast<LLTOperandMatcher>(&**InsnMatcher.predicates_begin())) + dyn_cast<LLTOperandMatcher>(&**InsnMatcher.predicates_begin())) { if (TM->getInsnVarID() == 0 && TM->getOpIdx() == 0) return TM->getTy(); + } + } return {}; } diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h index 543fd0a457939..5d1dc889f8523 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h @@ -47,6 +47,7 @@ class CodeGenRegisterClass; namespace gi { class MatchTable; class Matcher; +class RuleMatcher; class OperandMatcher; class MatchAction; class PredicateMatcher; @@ -70,8 +71,7 @@ std::string getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset, /// they share. \p MatcherStorage is used as a memory container /// for the group that are created as part of this process. /// -/// What this optimization does looks like if GroupT = GroupMatcher: -/// Output without optimization: +/// Example of GroupMatcher formation via this function: /// \verbatim /// # R1 /// # predicate A @@ -91,10 +91,9 @@ std::string getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset, /// # R2 /// # predicate C /// \endverbatim -template <class GroupT> std::vector<Matcher *> -optimizeRules(ArrayRef<Matcher *> Rules, - std::vector<std::unique_ptr<Matcher>> &MatcherStorage); +optimizeRuleset(MutableArrayRef<RuleMatcher> Rules, + std::vector<std::unique_ptr<Matcher>> &MatcherStorage); /// A record to be stored in a MatchTable. /// @@ -323,6 +322,7 @@ class Matcher { virtual bool hasFirstCondition() const = 0; virtual const PredicateMatcher &getFirstCondition() const = 0; + virtual LLTCodeGen getFirstConditionAsRootType() const = 0; virtual std::unique_ptr<PredicateMatcher> popFirstCondition() = 0; /// Check recursively if the matcher records named operands for use in C++ @@ -394,6 +394,7 @@ class GroupMatcher final : public Matcher { "Trying to get a condition from a condition-less group"); return *Conditions.front(); } + LLTCodeGen getFirstConditionAsRootType() const override; bool hasFirstCondition() const override { return !Conditions.empty(); } bool recordsOperand() const override; @@ -469,7 +470,11 @@ class SwitchMatcher : public Matcher { } const PredicateMatcher &getFirstCondition() const override { - llvm_unreachable("Trying to pop a condition from a condition-less group"); + llvm_unreachable("Trying to get a condition from a condition-less group"); + } + + LLTCodeGen getFirstConditionAsRootType() const override { + llvm_unreachable("Trying to get a condition from a condition-less group"); } bool hasFirstCondition() const override { return false; } @@ -720,7 +725,7 @@ class RuleMatcher : public Matcher { std::unique_ptr<PredicateMatcher> popFirstCondition() override; const PredicateMatcher &getFirstCondition() const override; - LLTCodeGen getFirstConditionAsRootType(); + LLTCodeGen getFirstConditionAsRootType() const override; bool hasFirstCondition() const override; StringRef getOpcode() const; diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index e01f2a2685049..deb126cbd716a 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -2712,41 +2712,8 @@ GICombinerEmitter::GICombinerEmitter(const RecordKeeper &RK, MatchTable GICombinerEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules) { - std::vector<Matcher *> InputRules; - for (Matcher &Rule : Rules) - InputRules.push_back(&Rule); - - unsigned CurrentOrdering = 0; - StringMap<unsigned> OpcodeOrder; - for (RuleMatcher &Rule : Rules) { - const StringRef Opcode = Rule.getOpcode(); - assert(!Opcode.empty() && "Didn't expect an undefined opcode"); - if (OpcodeOrder.try_emplace(Opcode, CurrentOrdering).second) - ++CurrentOrdering; - } - - llvm::stable_sort(InputRules, [&OpcodeOrder](const Matcher *A, - const Matcher *B) { - auto *L = static_cast<const RuleMatcher *>(A); - auto *R = static_cast<const RuleMatcher *>(B); - return std::tuple(OpcodeOrder[L->getOpcode()], - L->insnmatchers_front().getNumOperandMatchers()) < - std::tuple(OpcodeOrder[R->getOpcode()], - R->insnmatchers_front().getNumOperandMatchers()); - }); - - for (Matcher *Rule : InputRules) - Rule->optimize(); - std::vector<std::unique_ptr<Matcher>> MatcherStorage; - std::vector<Matcher *> OptRules = - optimizeRules<GroupMatcher>(InputRules, MatcherStorage); - - for (Matcher *Rule : OptRules) - Rule->optimize(); - - OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage); - + std::vector<Matcher *> OptRules = optimizeRuleset(Rules, MatcherStorage); return MatchTable::buildTable(OptRules, /*WithCoverage*/ false, /*IsCombiner*/ true); } diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index aa30525db83ca..e659906a6a112 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2309,44 +2309,15 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { MatchTable GlobalISelEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules, bool Optimize, bool WithCoverage) { - std::vector<Matcher *> InputRules; - for (Matcher &Rule : Rules) - InputRules.push_back(&Rule); - - if (!Optimize) + if (!Optimize) { + std::vector<Matcher *> InputRules; + for (Matcher &Rule : Rules) + InputRules.push_back(&Rule); return MatchTable::buildTable(InputRules, WithCoverage); - - unsigned CurrentOrdering = 0; - StringMap<unsigned> OpcodeOrder; - for (RuleMatcher &Rule : Rules) { - const StringRef Opcode = Rule.getOpcode(); - assert(!Opcode.empty() && "Didn't expect an undefined opcode"); - if (OpcodeOrder.try_emplace(Opcode, CurrentOrdering).second) - ++CurrentOrdering; } - llvm::stable_sort( - InputRules, [&OpcodeOrder](const Matcher *A, const Matcher *B) { - auto *L = static_cast<const RuleMatcher *>(A); - auto *R = static_cast<const RuleMatcher *>(B); - return std::tuple(OpcodeOrder[L->getOpcode()], - L->insnmatchers_front().getNumOperandMatchers()) < - std::tuple(OpcodeOrder[R->getOpcode()], - R->insnmatchers_front().getNumOperandMatchers()); - }); - - for (Matcher *Rule : InputRules) - Rule->optimize(); - std::vector<std::unique_ptr<Matcher>> MatcherStorage; - std::vector<Matcher *> OptRules = - optimizeRules<GroupMatcher>(InputRules, MatcherStorage); - - for (Matcher *Rule : OptRules) - Rule->optimize(); - - OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage); - + std::vector<Matcher *> OptRules = optimizeRuleset(Rules, MatcherStorage); return MatchTable::buildTable(OptRules, WithCoverage); } >From 21024a1e559e018421b4cb461db2ad2c531564d1 Mon Sep 17 00:00:00 2001 From: pvanhout <[email protected]> Date: Tue, 12 May 2026 12:59:25 +0200 Subject: [PATCH 2/3] Fix tests --- .../GlobalISel/preselect-process-phis.mir | 6 ++--- .../select-intrinsic-aarch64-sdiv.mir | 26 +++---------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir b/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir index 9c9ae861fd8e3..b36c25baabb63 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/preselect-process-phis.mir @@ -1,8 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -verify-machineinstrs -mtriple aarch64--- --run-pass=instruction-select -global-isel-abort=1 %s -o - | FileCheck %s -# XFAIL: * - --- name: test_loop_phi_fpr_to_gpr alignment: 4 @@ -57,7 +55,7 @@ body: | successors: %bb.2(0x80000000) %3:gpr(s16) = G_PHI %1(s16), %bb.1, %5(s16), %bb.2 - %5:fpr(f16) = G_FPTRUNC %8(s32) + %5:fpr(f16) = G_FPTRUNC %8(f32) G_STORE %3(s16), %4(p0) :: (store (s16) into `ptr undef`) G_BR %bb.2 @@ -116,7 +114,7 @@ body: | successors: %bb.2(0x80000000) %3:fpr(s16) = G_PHI %5(s16), %bb.2, %1(s16), %bb.1 - %5:fpr(f16) = G_FPTRUNC %8(s32) + %5:fpr(f16) = G_FPTRUNC %8(f32) G_STORE %3(s16), %4(p0) :: (store (s16) into `ptr undef`) G_BR %bb.2 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir index 82b5eff9b66a0..eeeddae96cefb 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir @@ -1,24 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -# XFAIL: * - -# MatchTable Before: -# /* 268430 */ GIM_Try, /*On fail goto*//*Label 4045*/ GIMT_Encode4(268475), // Rule ID 4220 // -# /* 268435 */ GIM_CheckNumOperands, /*MI*/0, /*Expected*/4, -# /* 268438 */ GIM_CheckIntrinsicID, /*MI*/0, /*Op*/1, GIMT_Encode2(Intrinsic::aarch64_sdiv), -# /* 268443 */ GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_i32, -# /* 268446 */ GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_i32, -# /* 268449 */ GIM_RootCheckType, /*Op*/3, /*Type*/GILLT_i32, -# -# MatchTable After: -# /* 241275 */ GIM_SwitchType, /*MI*/0, /*Op*/0, /*[*/GIMT_Encode2(7), GIMT_Encode2(9), /*)*//*default:*//*Label 6365*/ GIMT_Encode4(241364), -# /* 241286 */ /*GILLT_i32*//*Label 6363*/ GIMT_Encode4(241294), -# /* 241290 */ /*GILLT_i64*//*Label 6364*/ GIMT_Encode4(241329), -# -# Matching fails because type is S32 (index 2), but switch wants i32 (index 7). - - --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -48,8 +30,8 @@ body: | ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1 ; CHECK-NEXT: [[SDIVWr:%[0-9]+]]:gpr32 = SDIVWr [[COPY]], [[COPY1]] ; CHECK-NEXT: $w0 = COPY [[SDIVWr]] - %0(s32) = COPY $w0 - %1(s32) = COPY $w1 - %2(s32) = G_INTRINSIC intrinsic(@llvm.aarch64.sdiv.i32), %0, %1 - $w0 = COPY %2(s32) + %0(i32) = COPY $w0 + %1(i32) = COPY $w1 + %2(i32) = G_INTRINSIC intrinsic(@llvm.aarch64.sdiv.i32), %0, %1 + $w0 = COPY %2(i32) ... >From 2e548736350118696f776b37e5938d0f9a5fbf61 Mon Sep 17 00:00:00 2001 From: pvanhout <[email protected]> Date: Tue, 12 May 2026 14:12:20 +0200 Subject: [PATCH 3/3] Comments --- .../TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp | 5 +---- llvm/utils/TableGen/GlobalISelEmitter.cpp | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index d34388839e4a3..517ef0e92d716 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -149,10 +149,7 @@ optimizeRules(ArrayRef<Matcher *> Rules, std::vector<Matcher *> llvm::gi::optimizeRuleset( MutableArrayRef<RuleMatcher> Rules, std::vector<std::unique_ptr<Matcher>> &MatcherStorage) { - std::vector<Matcher *> InputRules; - InputRules.reserve(Rules.size()); - for (RuleMatcher &Rule : Rules) - InputRules.push_back(&Rule); + SmallVector<Matcher *> InputRules(make_pointer_range(Rules)); // Now sort the Rules. unsigned CurrentOrdering = 0; diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index e659906a6a112..813cf0f6c087b 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2310,9 +2310,7 @@ MatchTable GlobalISelEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules, bool Optimize, bool WithCoverage) { if (!Optimize) { - std::vector<Matcher *> InputRules; - for (Matcher &Rule : Rules) - InputRules.push_back(&Rule); + SmallVector<Matcher *> InputRules(make_pointer_range(Rules)); return MatchTable::buildTable(InputRules, WithCoverage); } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
