-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[TableGen][GISel] Learn to import patterns with physreg defs #120343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -362,13 +362,6 @@ foreach Index = 0...255 in { | |
| // Groupings using register classes and tuples | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| def SCC_CLASS : SIRegisterClass<"AMDGPU", [i1], 1, (add SCC)> { | ||
| let CopyCost = -1; | ||
| let isAllocatable = 0; | ||
| let HasSGPR = 1; | ||
| let BaseClassOrder = 10000; | ||
| } | ||
|
|
||
| def M0_CLASS : SIRegisterClass<"AMDGPU", [i32], 32, (add M0)> { | ||
| let CopyCost = 1; | ||
| let isAllocatable = 0; | ||
|
|
@@ -801,6 +794,14 @@ def SReg_32_XM0 : SIRegisterClass<"AMDGPU", [i32, f32, i16, f16, bf16, v2i16, v2 | |
|
|
||
| } // End GeneratePressureSet = 0 | ||
|
|
||
| def SCC_CLASS : SIRegisterClass<"AMDGPU", [i1], 1, (add SCC)> { | ||
| let CopyCost = -1; | ||
| let isAllocatable = 0; | ||
| let CrossCopyRegClass = SReg_32_XM0_XEXEC; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if this is correct. The class is the one returned by
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this should use one of the flavors of SReg_32. SReg_32 itself should be fine |
||
| let HasSGPR = 1; | ||
| let BaseClassOrder = 10000; | ||
| } | ||
|
|
||
| // Register class for all scalar registers (SGPRs + Special Registers) | ||
| def SReg_32 : SIRegisterClass<"AMDGPU", [i32, f32, i16, f16, bf16, v2i16, v2f16, v2bf16, i1], 32, | ||
| (add SReg_32_XM0, M0_CLASS)> { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,75 @@ | ||
| // RUN: llvm-tblgen -gen-global-isel -warn-on-skipped-patterns -I %p/../../../include -I %p/../Common %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not="Skipped pattern" | ||
| // RUN: llvm-tblgen -gen-global-isel -optimize-match-table=false \ | ||
| // RUN: -I %p/../../../include -I %p/../Common %s | ||
|
|
||
| include "llvm/Target/Target.td" | ||
| include "GlobalISelEmitterCommon.td" | ||
|
|
||
| // CHECK: Skipped pattern: Pattern defines a physical register | ||
| let Uses = [B0], Defs = [B0] in | ||
| def tst1 : I<(outs), (ins), [(set B0, (add B0, 1))]>; | ||
| let Defs = [R0, B0] in | ||
| def tst1 : I<(outs), (ins), [(set R0, (i32 42))]>; | ||
|
|
||
| // CHECK: Skipped pattern: Src pattern result has 1 def(s) without the HasNoUse predicate set to true but Dst MI has no def | ||
| let Uses = [B0] in | ||
| def tst2 : I<(outs), (ins), [(set B0, (add B0, 1))]>; | ||
| let Defs = [R0, R1] in | ||
| def tst2 : I<(outs GPR32:$rd), (ins GPR32:$rs1, GPR32:$rs2), | ||
| [(set GPR32:$rd, R1, (sdivrem i32:$rs1, i32:$rs2))]>; | ||
|
|
||
| let Defs = [R0, R1] in | ||
| def tst3 : I<(outs), (ins GPR32:$rs1, GPR32:$rs2), | ||
| [(set R1, R0, (udivrem i32:$rs1, i32:$rs2))]>; | ||
|
|
||
| let Defs = [R0] in | ||
| def tst4 : I<(outs GPR32:$rd), (ins GPR32:$rs), []>; | ||
|
|
||
| def : Pat<(sdivrem i32:$rs, 42), (tst4 (tst4 $rs))>; | ||
|
|
||
| // CHECK-LABEL: // (sdivrem:{ *:[i32] }:{ *:[i32] } i32:{ *:[i32] }:$rs, 42:{ *:[i32] }) => (tst4:{ *:[i32] }:{ *:[i32] } (tst4:{ *:[i32] }:{ *:[i32] } ?:{ *:[i32] }:$rs)) | ||
| // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, | ||
| // CHECK-NEXT: GIR_BuildMI, /*InsnID*/2, /*Opcode*/GIMT_Encode2(MyTarget::tst4), | ||
| // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/2, /*TempRegID*/0, /*TempRegFlags*/GIMT_Encode2(RegState::Define), | ||
| // CHECK-NEXT: GIR_Copy, /*NewInsnID*/2, /*OldInsnID*/0, /*OpIdx*/2, // rs | ||
| // CHECK-NEXT: GIR_SetImplicitDefDead, /*InsnID*/2, /*OpIdx for MyTarget::R0*/0, | ||
| // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/2, | ||
| // CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::tst4), | ||
| // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[rd] | ||
| // CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, | ||
| // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), | ||
| // CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/1, // DstI[R0] | ||
| // CHECK-NEXT: GIR_AddRegister, /*InsnID*/1, GIMT_Encode2(MyTarget::R0), /*AddRegisterRegFlags*/GIMT_Encode2(0), | ||
| // CHECK-NEXT: GIR_RootConstrainSelectedInstOperands, | ||
| // CHECK-NEXT: // GIR_Coverage, 3, | ||
| // CHECK-NEXT: GIR_EraseRootFromParent_Done, | ||
|
|
||
| // CHECK-LABEL: // 42:{ *:[i32] } => (tst1:{ *:[i32] }) | ||
| // CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::tst1), | ||
| // CHECK-NEXT: GIR_SetImplicitDefDead, /*InsnID*/0, /*OpIdx for MyTarget::B0*/1, | ||
| // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), | ||
| // CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // DstI[R0] | ||
| // CHECK-NEXT: GIR_AddRegister, /*InsnID*/1, GIMT_Encode2(MyTarget::R0), /*AddRegisterRegFlags*/GIMT_Encode2(0), | ||
| // CHECK-NEXT: GIR_RootConstrainSelectedInstOperands, | ||
| // CHECK-NEXT: // GIR_Coverage, 0, | ||
| // CHECK-NEXT: GIR_EraseRootFromParent_Done, | ||
|
|
||
| // CHECK-LABEL: // (sdivrem:{ *:[i32] }:{ *:[i32] } i32:{ *:[i32] }:$rs1, i32:{ *:[i32] }:$rs2) => (tst2:{ *:[i32] }:{ *:[i32] } i32:{ *:[i32] }:$rs1, i32:{ *:[i32] }:$rs2) | ||
| // CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::tst2), | ||
| // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // DstI[rd] | ||
| // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/2, // rs1 | ||
| // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/3, // rs2 | ||
| // CHECK-NEXT: GIR_SetImplicitDefDead, /*InsnID*/0, /*OpIdx for MyTarget::R1*/1, | ||
| // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), | ||
| // CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/1, // DstI[R0] | ||
| // CHECK-NEXT: GIR_AddRegister, /*InsnID*/1, GIMT_Encode2(MyTarget::R0), /*AddRegisterRegFlags*/GIMT_Encode2(0), | ||
| // CHECK-NEXT: GIR_RootConstrainSelectedInstOperands, | ||
| // CHECK-NEXT: // GIR_Coverage, 1, | ||
| // CHECK-NEXT: GIR_EraseRootFromParent_Done, | ||
|
|
||
| // CHECK-LABEL: // (udivrem:{ *:[i32] }:{ *:[i32] } i32:{ *:[i32] }:$rs1, i32:{ *:[i32] }:$rs2) => (tst3:{ *:[i32] } i32:{ *:[i32] }:$rs1, i32:{ *:[i32] }:$rs2) | ||
| // CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(MyTarget::tst3), | ||
| // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/2, // rs1 | ||
| // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/3, // rs2 | ||
| // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), | ||
| // CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // DstI[R0] | ||
| // CHECK-NEXT: GIR_AddRegister, /*InsnID*/1, GIMT_Encode2(MyTarget::R0), /*AddRegisterRegFlags*/GIMT_Encode2(0), | ||
| // CHECK-NEXT: GIR_BuildMI, /*InsnID*/2, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), | ||
| // CHECK-NEXT: GIR_Copy, /*NewInsnID*/2, /*OldInsnID*/0, /*OpIdx*/1, // DstI[R1] | ||
| // CHECK-NEXT: GIR_AddRegister, /*InsnID*/2, GIMT_Encode2(MyTarget::R1), /*AddRegisterRegFlags*/GIMT_Encode2(0), | ||
| // CHECK-NEXT: GIR_RootConstrainSelectedInstOperands, | ||
| // CHECK-NEXT: // GIR_Coverage, 2, | ||
| // CHECK-NEXT: GIR_EraseRootFromParent_Done, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs documentation. Also this doesn't seem like the right terminology. It's more of a virtual register class to use for copies with an unallocatable physical register, not a general cross copy. Maybe AllocatableRegClass?