From 6cb814d4aab2439b5b2356c553671002b146cf6d Mon Sep 17 00:00:00 2001 From: Pete Chou Date: Wed, 12 Feb 2025 21:23:35 -0800 Subject: [PATCH 1/2] [TableGen] Inherit properties from the nearest allocatable superclass. Previously isAlocatable was updated to allow inheritance from any superclass for a generated register class, but other properties are still inherited from its nearest superclass. This could cause a generated regclass inherit undesired properties, e.g., tsflags, from an unallocatable superclass due to the topological inheritance order. This change updates to inherit properties from the nearest allocatable superclass if possible and includes a test to demonstrate a potential incorrect inheritance of tsflags. --- .../RegisterInfoEmitter-inherit-properties.td | 87 +++++++++++++++++++ .../TableGen/Common/CodeGenRegisters.cpp | 18 ++-- 2 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td diff --git a/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td b/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td new file mode 100644 index 0000000000000..9ca3478662ce9 --- /dev/null +++ b/llvm/test/TableGen/RegisterInfoEmitter-inherit-properties.td @@ -0,0 +1,87 @@ +// RUN: llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s | FileCheck %s + +// This file tests that a synthesized sub-regclass can inherit properties, e.g., +// tsflags in this case, from the correct super-regclass. + +include "llvm/Target/Target.td" + +class MyReg subregs = []> + : Register { + let Namespace = "Test"; + let SubRegs = subregs; + let CoveredBySubRegs = 1; +} + +class MyClass types, dag registers> + : RegisterClass<"Test", types, align, registers> { + field bit isA = 0; + field bit isB = 0; + let TSFlags{0} = isA; + let TSFlags{1} = isB; +} + +def sub0 : SubRegIndex<32, 0>; +def sub1 : SubRegIndex<32, 32>; +def sub2 : SubRegIndex<32, 64>; + +foreach Num=0-7 in { + def A#Num : MyReg<"a"#Num>; +} + +foreach Num=0-3 in { + def B#Num : MyReg<"b"#Num>; +} + +class AClass types, dag registers> + : MyClass { + let isA = 1; +} + +class BClass types, dag registers> + : MyClass { + let isB = 1; +} + +def APair : RegisterTuples<[sub0, sub1], + [(add A0, A2, A4, A6), (add A1, A3, A5, A7)]>; +def BPair : RegisterTuples<[sub0, sub1], + [(add B0, B2), (add B1, B3)]>; +def ARC2 : AClass<32, [untyped], (add APair)>; +def BRC2 : BClass<32, [untyped], (add BPair)>; +def ABRC2 : MyClass<32, [untyped], (add ARC2, BRC2)> { + let isAllocatable = 0; +} + +def ATuple : RegisterTuples<[sub0, sub1, sub2], + [(add A0, A1, A2, A3, A4, A5), + (add A1, A2, A3, A4, A5, A6), + (add A2, A3, A4, A5, A6, A7)]>; + +def BTuple : RegisterTuples<[sub0, sub1, sub2], + [(add B0, B1), (add B1, B2), (add B2, B3)]>; + +def ARC3 : AClass<32, [untyped], (add ATuple)>; +def BRC3 : BClass<32, [untyped], (add BTuple)>; +def ABRC3 : MyClass<32, [untyped], (add ARC3, BRC3)> { + let isAllocatable = 0; +} + +def TestTarget : Target; + +// CHECK: static unsigned const ARC3_with_sub0_sub1Superclasses[] = { +// CHECK-NEXT: Test::ABRC3RegClassID, +// CHECK-NEXT: Test::ARC3RegClassID, +// CHECK-NEXT: Test::ABRC3_with_sub0_sub1RegClassID, +// CHECK-NEXT: }; + +// CHECK: static unsigned const ARC3_with_sub1_sub2Superclasses[] = { +// CHECK-NEXT: Test::ABRC3RegClassID, +// CHECK-NEXT: Test::ARC3RegClassID, +// CHECK-NEXT: Test::ABRC3_with_sub1_sub2RegClassID, +// CHECK-NEXT: }; + +// CHECK: extern const TargetRegisterClass ARC3_with_sub0_sub1RegClass = { +// CHECK: 0x01, /* TSFlags */ + +// CHECK: extern const TargetRegisterClass ARC3_with_sub1_sub2RegClass = { +// CHECK: 0x01, /* TSFlags */ diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp index e732bbcf525e9..262d7e5186f16 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -861,23 +861,27 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, } } -// Compute inherited propertied for a synthesized register class. +// Compute inherited properties for a synthesized register class. void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) { assert(!getDef() && "Only synthesized classes can inherit properties"); assert(!SuperClasses.empty() && "Synthesized class without super class"); - // The last super-class is the smallest one. - CodeGenRegisterClass &Super = *SuperClasses.back(); + // The last super-class is the smallest one in topological order. Check for + // allocatable super-classes and inherit from the nearest allocatable one if + // any. + auto NearestAllocSCRIt = std::find_if( + SuperClasses.rbegin(), SuperClasses.rend(), + [&](const CodeGenRegisterClass *S) { return S->Allocatable; }); + CodeGenRegisterClass &Super = NearestAllocSCRIt == SuperClasses.rend() + ? *SuperClasses.back() + : **NearestAllocSCRIt; // Most properties are copied directly. // Exceptions are members, size, and alignment Namespace = Super.Namespace; VTs = Super.VTs; CopyCost = Super.CopyCost; - // Check for allocatable superclasses. - Allocatable = any_of(SuperClasses, [&](const CodeGenRegisterClass *S) { - return S->Allocatable; - }); + Allocatable = Super.Allocatable; AltOrderSelect = Super.AltOrderSelect; AllocationPriority = Super.AllocationPriority; GlobalPriority = Super.GlobalPriority; From 82f55877ba72e5110723afd190b28d5ae402ccee Mon Sep 17 00:00:00 2001 From: Pete Chou Date: Tue, 25 Mar 2025 10:58:27 -0700 Subject: [PATCH 2/2] use llvm::find_if with reverse to find the last occurrence. --- llvm/utils/TableGen/Common/CodeGenRegisters.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp index 262d7e5186f16..43b9c04eab20a 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -869,9 +869,9 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) { // The last super-class is the smallest one in topological order. Check for // allocatable super-classes and inherit from the nearest allocatable one if // any. - auto NearestAllocSCRIt = std::find_if( - SuperClasses.rbegin(), SuperClasses.rend(), - [&](const CodeGenRegisterClass *S) { return S->Allocatable; }); + auto NearestAllocSCRIt = + find_if(reverse(SuperClasses), + [&](const CodeGenRegisterClass *S) { return S->Allocatable; }); CodeGenRegisterClass &Super = NearestAllocSCRIt == SuperClasses.rend() ? *SuperClasses.back() : **NearestAllocSCRIt;