[llvm] [AArch64][GlobalISel] Constrain G_CONSTANT_FOLD_BARRIER operand register classes (PR #177997)
Cullen Rhodes via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 30 06:03:41 PST 2026
https://github.com/c-rhodes updated https://github.com/llvm/llvm-project/pull/177997
>From d3e9fc89f6adbcbf0f74c97d67f4d7dbd83de092 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Fri, 23 Jan 2026 15:42:10 +0000
Subject: [PATCH 1/6] [AArch64][GlobalISel] Constrain G_AND operands to GPR64
register class
Instruction selection is lowering:
bb.1:
%6:gpr(s64) = G_CONSTANT i64 457873110
...
bb.2:
%12:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
%24:gpr(s64) = G_CONSTANT i64 0
%13:gpr(s64) = G_AND %24, %12
...
to:
%13:gpr64 = ANDXrr %24:gpr64, %6:gpr64sp'
which is causing the verifier to fail with:
Expected a GPR64 register, but got a GPR64sp register
this patch fixes this by constraining the G_AND operand(s) register
class to GPR64.
Fixes #166563.
---
.../GISel/AArch64InstructionSelector.cpp | 40 +++
.../CodeGen/AArch64/GlobalISel/166563.mir | 245 ++++++++++++++++++
2 files changed, 285 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 7605bbea51f56..55b4ad9626116 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2359,6 +2359,46 @@ bool AArch64InstructionSelector::earlySelect(MachineInstr &I) {
I.eraseFromParent();
return true;
}
+ case TargetOpcode::G_AND: {
+ Register Dst = I.getOperand(0).getReg();
+ Register LHS = I.getOperand(1).getReg();
+ Register RHS = I.getOperand(2).getReg();
+ LLT Ty = MRI.getType(Dst);
+
+ if (Ty.isVector() || Ty.getSizeInBits() != 64)
+ return false;
+
+ auto match = [&](Register Op1, Register Op2) {
+ auto Op1Cst = getIConstantVRegValWithLookThrough(Op1, MRI);
+ if (!(Op1Cst && Op1Cst->Value == 0))
+ return false;
+ // Expecting a G_CONSTANT_FOLD_BARRIER that can't be looked thru.
+ auto Op2Cst = getIConstantVRegValWithLookThrough(Op2, MRI);
+ if (Op2Cst)
+ return false;
+ return true;
+ };
+
+ if (!match(LHS, RHS) && !match(RHS, LHS))
+ return false;
+
+ // Copy either operand into plain GPR class if necessary so the opcode is
+ // legal.
+ auto moveToGPR64 = [&](Register &Reg) {
+ const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
+ if (!Reg.isVirtual() || (RC && RC == &AArch64::GPR64RegClass))
+ return;
+ auto Copy = MIB.buildCopy({&AArch64::GPR64RegClass}, {Reg});
+ selectCopy(*Copy, TII, MRI, TRI, RBI);
+ Reg = Copy.getReg(0);
+ };
+
+ moveToGPR64(LHS);
+ moveToGPR64(RHS);
+ auto NewAnd = MIB.buildInstr(AArch64::ANDXrr, {Dst}, {LHS, RHS});
+ I.eraseFromParent();
+ return constrainSelectedInstRegOperands(*NewAnd, TII, TRI, RBI);
+ }
case TargetOpcode::G_SEXT:
// Check for i64 sext(i32 vector_extract) prior to tablegen to select SMOV
// over a normal extend.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
new file mode 100644
index 0000000000000..a6b2001376b37
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
@@ -0,0 +1,245 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -run-pass=instruction-select -verify-machineinstrs -mtriple aarch64 %s -o - | FileCheck %s
+
+# Crash reproducer from: https://github.com/llvm/llvm-project/issues/166563
+
+---
+name: pr166563
+alignment: 4
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+liveins:
+ - { reg: '$w0', virtual-reg: '' }
+body: |
+ ; CHECK-LABEL: name: pr166563
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.2(0x30000000), %bb.1(0x50000000)
+ ; CHECK-NEXT: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 457873110
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64sp = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
+ ; CHECK-NEXT: [[MOVi32imm1:%[0-9]+]]:gpr32 = MOVi32imm 1
+ ; CHECK-NEXT: TBNZW [[MOVi32imm1]], 0, %bb.2
+ ; CHECK-NEXT: B %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.6(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: B %bb.6
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.4(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: TBZW [[COPY]], 0, %bb.4
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: successors: %bb.5(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri [[SUBREG_TO_REG]], 2, 0, implicit-def dead $nzcv
+ ; CHECK-NEXT: B %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4:
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $xzr
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]]
+ ; CHECK-NEXT: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: $x0 = COPY [[ANDXrr]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: successors: %bb.5(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PHI:%[0-9]+]]:gpr64sp = PHI [[SUBSXri]], %bb.3, %14, %bb.5
+ ; CHECK-NEXT: [[SUBSXri1:%[0-9]+]]:gpr64 = SUBSXri [[PHI]], 1, 0, implicit-def dead $nzcv
+ ; CHECK-NEXT: B %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.6:
+ ; CHECK-NEXT: successors: %bb.7(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.7:
+ ; CHECK-NEXT: successors: %bb.7(0x7c000000), %bb.6(0x04000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[SUBSXri2:%[0-9]+]]:gpr64 = SUBSXri [[SUBREG_TO_REG]], 0, 0, implicit-def $nzcv
+ ; CHECK-NEXT: Bcc 8, %bb.7, implicit $nzcv
+ ; CHECK-NEXT: B %bb.6
+ bb.1:
+ successors: %bb.3(0x30000000), %bb.2(0x50000000)
+ liveins: $w0
+
+ %2:gpr(s32) = COPY $w0
+ %6:gpr(s64) = G_CONSTANT i64 457873110
+ %36:gpr(s32) = G_CONSTANT i32 1
+ G_BRCOND %36(s32), %bb.3
+ G_BR %bb.2
+
+ bb.2:
+ successors: %bb.7(0x80000000)
+
+ %7:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ G_BR %bb.7
+
+ bb.3:
+ successors: %bb.4(0x40000000), %bb.5(0x40000000)
+
+ %28:gpr(s32) = G_CONSTANT i32 1
+ %29:gpr(s32) = G_XOR %2, %28
+ %26:gpr(s32) = G_AND %29, %28
+ G_BRCOND %26(s32), %bb.5
+ G_BR %bb.4
+
+ bb.4:
+ successors: %bb.6(0x80000000)
+
+ %14:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ %23:gpr(s64) = G_CONSTANT i64 -2
+ %16:gpr(s64) = G_ADD %14, %23
+ G_BR %bb.6
+
+ bb.5:
+ %12:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ %24:gpr(s64) = G_CONSTANT i64 0
+ %13:gpr(s64) = G_AND %24, %12
+ $x0 = COPY %13(s64)
+ RET_ReallyLR implicit $x0
+
+ bb.6:
+ successors: %bb.6(0x80000000)
+
+ %17:gpr(s64) = G_PHI %16(s64), %bb.4, %19(s64), %bb.6
+ %22:gpr(s64) = G_CONSTANT i64 -1
+ %19:gpr(s64) = G_ADD %17, %22
+ G_BR %bb.6
+
+ bb.7:
+ successors: %bb.8(0x80000000)
+
+ bb.8:
+ successors: %bb.8(0x7c000000), %bb.7(0x04000000)
+
+ %25:gpr(s64) = G_CONSTANT i64 0
+ %32:gpr(s32) = G_ICMP intpred(ugt), %7(s64), %25
+ G_BRCOND %32(s32), %bb.8
+ G_BR %bb.7
+...
+---
+name: pr166563_commuted_and
+alignment: 4
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+liveins:
+ - { reg: '$w0', virtual-reg: '' }
+body: |
+ ; CHECK-LABEL: name: pr166563_commuted_and
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.2(0x30000000), %bb.1(0x50000000)
+ ; CHECK-NEXT: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+ ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 457873110
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64sp = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
+ ; CHECK-NEXT: [[MOVi32imm1:%[0-9]+]]:gpr32 = MOVi32imm 1
+ ; CHECK-NEXT: TBNZW [[MOVi32imm1]], 0, %bb.2
+ ; CHECK-NEXT: B %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.6(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: B %bb.6
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.4(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: TBZW [[COPY]], 0, %bb.4
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: successors: %bb.5(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri [[SUBREG_TO_REG]], 2, 0, implicit-def dead $nzcv
+ ; CHECK-NEXT: B %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4:
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $xzr
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]]
+ ; CHECK-NEXT: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY2]], [[COPY1]]
+ ; CHECK-NEXT: $x0 = COPY [[ANDXrr]]
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: successors: %bb.5(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PHI:%[0-9]+]]:gpr64sp = PHI [[SUBSXri]], %bb.3, %14, %bb.5
+ ; CHECK-NEXT: [[SUBSXri1:%[0-9]+]]:gpr64 = SUBSXri [[PHI]], 1, 0, implicit-def dead $nzcv
+ ; CHECK-NEXT: B %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.6:
+ ; CHECK-NEXT: successors: %bb.7(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.7:
+ ; CHECK-NEXT: successors: %bb.7(0x7c000000), %bb.6(0x04000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[SUBSXri2:%[0-9]+]]:gpr64 = SUBSXri [[SUBREG_TO_REG]], 0, 0, implicit-def $nzcv
+ ; CHECK-NEXT: Bcc 8, %bb.7, implicit $nzcv
+ ; CHECK-NEXT: B %bb.6
+ bb.1:
+ successors: %bb.3(0x30000000), %bb.2(0x50000000)
+ liveins: $w0
+
+ %2:gpr(s32) = COPY $w0
+ %6:gpr(s64) = G_CONSTANT i64 457873110
+ %36:gpr(s32) = G_CONSTANT i32 1
+ G_BRCOND %36(s32), %bb.3
+ G_BR %bb.2
+
+ bb.2:
+ successors: %bb.7(0x80000000)
+
+ %7:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ G_BR %bb.7
+
+ bb.3:
+ successors: %bb.4(0x40000000), %bb.5(0x40000000)
+
+ %28:gpr(s32) = G_CONSTANT i32 1
+ %29:gpr(s32) = G_XOR %2, %28
+ %26:gpr(s32) = G_AND %29, %28
+ G_BRCOND %26(s32), %bb.5
+ G_BR %bb.4
+
+ bb.4:
+ successors: %bb.6(0x80000000)
+
+ %14:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ %23:gpr(s64) = G_CONSTANT i64 -2
+ %16:gpr(s64) = G_ADD %14, %23
+ G_BR %bb.6
+
+ bb.5:
+ %12:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ %24:gpr(s64) = G_CONSTANT i64 0
+ %13:gpr(s64) = G_AND %12, %24
+ $x0 = COPY %13(s64)
+ RET_ReallyLR implicit $x0
+
+ bb.6:
+ successors: %bb.6(0x80000000)
+
+ %17:gpr(s64) = G_PHI %16(s64), %bb.4, %19(s64), %bb.6
+ %22:gpr(s64) = G_CONSTANT i64 -1
+ %19:gpr(s64) = G_ADD %17, %22
+ G_BR %bb.6
+
+ bb.7:
+ successors: %bb.8(0x80000000)
+
+ bb.8:
+ successors: %bb.8(0x7c000000), %bb.7(0x04000000)
+
+ %25:gpr(s64) = G_CONSTANT i64 0
+ %32:gpr(s32) = G_ICMP intpred(ugt), %7(s64), %25
+ G_BRCOND %32(s32), %bb.8
+ G_BR %bb.7
+...
>From 09c0c9c3e34d6e499dde800116e23d864a0d3aa8 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Tue, 27 Jan 2026 11:16:56 +0000
Subject: [PATCH 2/6] constrain G_CONSTANT_FOLD_BARRIER
---
.../CodeGen/GlobalISel/InstructionSelect.cpp | 9 ++-
.../GISel/AArch64InstructionSelector.cpp | 61 +++++++------------
.../CodeGen/AArch64/GlobalISel/166563.mir | 10 ++-
3 files changed, 33 insertions(+), 47 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index fc379b5f19d5a..4b1a8a34ab3fc 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -356,7 +356,14 @@ bool InstructionSelect::selectInstr(MachineInstr &MI) {
return true;
}
- // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
+ if (MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
+ // Allow targets to provide custom handling before falling back to the
+ // generic elimination below.
+ if (ISel->select(MI))
+ return true;
+ }
+
+ // Eliminate hints or a remaining G_CONSTANT_FOLD_BARRIER.
if (isPreISelGenericOptimizationHint(MI.getOpcode()) ||
MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
auto [DstReg, SrcReg] = MI.getFirst2Regs();
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 55b4ad9626116..36e2c689aba13 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2359,46 +2359,6 @@ bool AArch64InstructionSelector::earlySelect(MachineInstr &I) {
I.eraseFromParent();
return true;
}
- case TargetOpcode::G_AND: {
- Register Dst = I.getOperand(0).getReg();
- Register LHS = I.getOperand(1).getReg();
- Register RHS = I.getOperand(2).getReg();
- LLT Ty = MRI.getType(Dst);
-
- if (Ty.isVector() || Ty.getSizeInBits() != 64)
- return false;
-
- auto match = [&](Register Op1, Register Op2) {
- auto Op1Cst = getIConstantVRegValWithLookThrough(Op1, MRI);
- if (!(Op1Cst && Op1Cst->Value == 0))
- return false;
- // Expecting a G_CONSTANT_FOLD_BARRIER that can't be looked thru.
- auto Op2Cst = getIConstantVRegValWithLookThrough(Op2, MRI);
- if (Op2Cst)
- return false;
- return true;
- };
-
- if (!match(LHS, RHS) && !match(RHS, LHS))
- return false;
-
- // Copy either operand into plain GPR class if necessary so the opcode is
- // legal.
- auto moveToGPR64 = [&](Register &Reg) {
- const TargetRegisterClass *RC = MRI.getRegClassOrNull(Reg);
- if (!Reg.isVirtual() || (RC && RC == &AArch64::GPR64RegClass))
- return;
- auto Copy = MIB.buildCopy({&AArch64::GPR64RegClass}, {Reg});
- selectCopy(*Copy, TII, MRI, TRI, RBI);
- Reg = Copy.getReg(0);
- };
-
- moveToGPR64(LHS);
- moveToGPR64(RHS);
- auto NewAnd = MIB.buildInstr(AArch64::ANDXrr, {Dst}, {LHS, RHS});
- I.eraseFromParent();
- return constrainSelectedInstRegOperands(*NewAnd, TII, TRI, RBI);
- }
case TargetOpcode::G_SEXT:
// Check for i64 sext(i32 vector_extract) prior to tablegen to select SMOV
// over a normal extend.
@@ -2819,6 +2779,27 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
return true;
}
+ case TargetOpcode::G_CONSTANT_FOLD_BARRIER: {
+ auto ConstrainToRC = [&](Register Reg) {
+ const RegisterBank &RB = *RBI.getRegBank(Reg, MRI, TRI);
+ const TargetRegisterClass *RC =
+ getRegClassForTypeOnBank(MRI.getType(Reg), RB);
+ return RC && RBI.constrainGenericRegister(Reg, *RC, MRI);
+ };
+
+ auto [DstReg, SrcReg] = I.getFirst2Regs();
+ if (!ConstrainToRC(DstReg) || !ConstrainToRC(SrcReg))
+ return false;
+
+ if (const auto *DstRC = MRI.getRegClassOrNull(DstReg))
+ MRI.setRegClass(SrcReg, DstRC);
+
+ assert(canReplaceReg(DstReg, SrcReg, MRI) &&
+ "Must be able to replace dst with src!");
+ I.eraseFromParent();
+ MRI.replaceRegWith(DstReg, SrcReg);
+ return true;
+ }
case TargetOpcode::G_EXTRACT: {
Register DstReg = I.getOperand(0).getReg();
Register SrcReg = I.getOperand(1).getReg();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
index a6b2001376b37..7e376f4f3c394 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
@@ -19,7 +19,7 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 457873110
- ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64sp = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64common = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
; CHECK-NEXT: [[MOVi32imm1:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK-NEXT: TBNZW [[MOVi32imm1]], 0, %bb.2
; CHECK-NEXT: B %bb.1
@@ -43,8 +43,7 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.4:
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $xzr
- ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]]
- ; CHECK-NEXT: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY1]], [[SUBREG_TO_REG]]
; CHECK-NEXT: $x0 = COPY [[ANDXrr]]
; CHECK-NEXT: RET_ReallyLR implicit $x0
; CHECK-NEXT: {{ $}}
@@ -139,7 +138,7 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 457873110
- ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64sp = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64common = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
; CHECK-NEXT: [[MOVi32imm1:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK-NEXT: TBNZW [[MOVi32imm1]], 0, %bb.2
; CHECK-NEXT: B %bb.1
@@ -163,8 +162,7 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.4:
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $xzr
- ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[SUBREG_TO_REG]]
- ; CHECK-NEXT: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY2]], [[COPY1]]
+ ; CHECK-NEXT: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[SUBREG_TO_REG]], [[COPY1]]
; CHECK-NEXT: $x0 = COPY [[ANDXrr]]
; CHECK-NEXT: RET_ReallyLR implicit $x0
; CHECK-NEXT: {{ $}}
>From 12e2fa2827e1ed1ce1d72134f807b659da28a402 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Wed, 28 Jan 2026 13:44:22 +0000
Subject: [PATCH 3/6] move fix to generic selection
---
.../include/llvm/CodeGen/TargetRegisterInfo.h | 9 ++
.../CodeGen/GlobalISel/InstructionSelect.cpp | 21 ++--
.../Target/AArch64/AArch64RegisterInfo.cpp | 34 ++++++
llvm/lib/Target/AArch64/AArch64RegisterInfo.h | 4 +
.../GISel/AArch64InstructionSelector.cpp | 111 +++++-------------
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 5 +-
.../Target/Mips/MipsInstructionSelector.cpp | 42 ++-----
llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 31 +++++
llvm/lib/Target/Mips/MipsRegisterInfo.h | 4 +
.../RISCV/GISel/RISCVInstructionSelector.cpp | 48 ++------
llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 37 ++++++
llvm/lib/Target/RISCV/RISCVRegisterInfo.h | 4 +
12 files changed, 183 insertions(+), 167 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 35b14e8b8fd30..2fbbe0ee0932e 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/RegisterBank.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -382,6 +383,14 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
const TargetRegisterClass *
getAllocatableClass(const TargetRegisterClass *RC) const;
+ /// Given a register bank, and a type, return the smallest register class
+ /// that can represent that combination.
+ virtual const TargetRegisterClass *
+ getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank,
+ const TargetSubtargetInfo *STI = nullptr) const {
+ return nullptr;
+ }
+
/// Returns a bitset indexed by register number indicating if a register is
/// allocatable or not. If a register class is specified, returns the subset
/// for the class.
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index 4b1a8a34ab3fc..c689413cc1293 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -356,17 +357,21 @@ bool InstructionSelect::selectInstr(MachineInstr &MI) {
return true;
}
- if (MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
- // Allow targets to provide custom handling before falling back to the
- // generic elimination below.
- if (ISel->select(MI))
- return true;
- }
-
- // Eliminate hints or a remaining G_CONSTANT_FOLD_BARRIER.
+ // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
if (isPreISelGenericOptimizationHint(MI.getOpcode()) ||
MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
+ const RegisterBankInfo *RBI = ISel->MF->getSubtarget().getRegBankInfo();
+ const TargetRegisterInfo *TRI = ISel->MF->getSubtarget().getRegisterInfo();
+ auto ConstrainToRC = [&](Register Reg) {
+ const RegisterBank *RB = RBI->getRegBank(Reg, MRI, *TRI);
+ const TargetRegisterClass *RC = TRI->getRegClassForTypeOnBank(
+ MRI.getType(Reg), *RB, &ISel->MF->getSubtarget());
+ return !RC || (RC && RBI->constrainGenericRegister(Reg, *RC, MRI));
+ };
+
auto [DstReg, SrcReg] = MI.getFirst2Regs();
+ if (!ConstrainToRC(DstReg) || !ConstrainToRC(SrcReg))
+ return false;
// At this point, the destination register class of the op may have
// been decided.
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index 8c0dd4381fae8..86003693973a8 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -17,6 +17,7 @@
#include "AArch64MachineFunctionInfo.h"
#include "AArch64SMEAttributes.h"
#include "AArch64Subtarget.h"
+#include "GISel/AArch64RegisterBankInfo.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "MCTargetDesc/AArch64InstPrinter.h"
#include "llvm/ADT/BitVector.h"
@@ -1442,3 +1443,36 @@ bool AArch64RegisterInfo::isIgnoredCVReg(MCRegister LLVMReg) const {
return (LLVMReg >= AArch64::Z0 && LLVMReg <= AArch64::Z31) ||
(LLVMReg >= AArch64::P0 && LLVMReg <= AArch64::P15);
}
+
+// FIXME: This should be target-independent, inferred from the types declared
+// for each class in the bank.
+const TargetRegisterClass *AArch64RegisterInfo::getRegClassForTypeOnBank(
+ LLT Ty, const RegisterBank &RB, const TargetSubtargetInfo *STI) const {
+ if (RB.getID() == AArch64::GPRRegBankID) {
+ if (Ty.getSizeInBits() <= 32)
+ return &AArch64::GPR32RegClass;
+ if (Ty.getSizeInBits() == 64)
+ return &AArch64::GPR64RegClass;
+ if (Ty.getSizeInBits() == 128)
+ return &AArch64::XSeqPairsClassRegClass;
+ return nullptr;
+ }
+
+ if (RB.getID() == AArch64::FPRRegBankID) {
+ switch (Ty.getSizeInBits()) {
+ case 8:
+ return &AArch64::FPR8RegClass;
+ case 16:
+ return &AArch64::FPR16RegClass;
+ case 32:
+ return &AArch64::FPR32RegClass;
+ case 64:
+ return &AArch64::FPR64RegClass;
+ case 128:
+ return &AArch64::FPR128RegClass;
+ }
+ return nullptr;
+ }
+
+ return nullptr;
+}
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index 89d1802ab98d5..7ce922aee3f97 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -154,6 +154,10 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
bool shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const override;
bool isIgnoredCVReg(MCRegister LLVMReg) const override;
+
+ const TargetRegisterClass *getRegClassForTypeOnBank(
+ LLT Ty, const RegisterBank &Bank,
+ const TargetSubtargetInfo *STI = nullptr) const override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 36e2c689aba13..46d1d2c1029bd 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -564,45 +564,6 @@ AArch64InstructionSelector::AArch64InstructionSelector(
{
}
-// FIXME: This should be target-independent, inferred from the types declared
-// for each class in the bank.
-//
-/// Given a register bank, and a type, return the smallest register class that
-/// can represent that combination.
-static const TargetRegisterClass *
-getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB,
- bool GetAllRegSet = false) {
- if (RB.getID() == AArch64::GPRRegBankID) {
- if (Ty.getSizeInBits() <= 32)
- return GetAllRegSet ? &AArch64::GPR32allRegClass
- : &AArch64::GPR32RegClass;
- if (Ty.getSizeInBits() == 64)
- return GetAllRegSet ? &AArch64::GPR64allRegClass
- : &AArch64::GPR64RegClass;
- if (Ty.getSizeInBits() == 128)
- return &AArch64::XSeqPairsClassRegClass;
- return nullptr;
- }
-
- if (RB.getID() == AArch64::FPRRegBankID) {
- switch (Ty.getSizeInBits()) {
- case 8:
- return &AArch64::FPR8RegClass;
- case 16:
- return &AArch64::FPR16RegClass;
- case 32:
- return &AArch64::FPR32RegClass;
- case 64:
- return &AArch64::FPR64RegClass;
- case 128:
- return &AArch64::FPR128RegClass;
- }
- return nullptr;
- }
-
- return nullptr;
-}
-
/// Given a register bank, and size in bits, return the smallest register class
/// that can represent that combination.
static const TargetRegisterClass *
@@ -1000,7 +961,9 @@ static bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI,
dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
if (!RC) {
const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
- RC = getRegClassForTypeOnBank(Ty, RB);
+ const TargetRegisterInfo *TRI =
+ I.getMF()->getSubtarget().getRegisterInfo();
+ RC = TRI->getRegClassForTypeOnBank(Ty, RB);
if (!RC) {
LLVM_DEBUG(
dbgs() << "Warning: DBG_VALUE operand has unexpected size/bank\n");
@@ -1904,7 +1867,7 @@ bool AArch64InstructionSelector::selectVectorAshrLshr(
unsigned Opc = 0;
unsigned NegOpc = 0;
const TargetRegisterClass *RC =
- getRegClassForTypeOnBank(Ty, RBI.getRegBank(AArch64::FPRRegBankID));
+ TRI.getRegClassForTypeOnBank(Ty, RBI.getRegBank(AArch64::FPRRegBankID));
if (Ty == LLT::fixed_vector(2, 64)) {
Opc = IsASHR ? AArch64::SSHLv2i64 : AArch64::USHLv2i64;
NegOpc = AArch64::NEGv2i64;
@@ -2543,7 +2506,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
return false;
}
const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
- DefRC = getRegClassForTypeOnBank(DefTy, RB);
+ DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
if (!DefRC) {
LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
return false;
@@ -2717,7 +2680,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
}
if (isFP) {
- const TargetRegisterClass &FPRRC = *getRegClassForTypeOnBank(DefTy, RB);
+ const TargetRegisterClass &FPRRC =
+ *TRI.getRegClassForTypeOnBank(DefTy, RB);
// For 16, 64, and 128b values, emit a constant pool load.
switch (DefSize) {
default:
@@ -2779,27 +2743,6 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
return true;
}
- case TargetOpcode::G_CONSTANT_FOLD_BARRIER: {
- auto ConstrainToRC = [&](Register Reg) {
- const RegisterBank &RB = *RBI.getRegBank(Reg, MRI, TRI);
- const TargetRegisterClass *RC =
- getRegClassForTypeOnBank(MRI.getType(Reg), RB);
- return RC && RBI.constrainGenericRegister(Reg, *RC, MRI);
- };
-
- auto [DstReg, SrcReg] = I.getFirst2Regs();
- if (!ConstrainToRC(DstReg) || !ConstrainToRC(SrcReg))
- return false;
-
- if (const auto *DstRC = MRI.getRegClassOrNull(DstReg))
- MRI.setRegClass(SrcReg, DstRC);
-
- assert(canReplaceReg(DstReg, SrcReg, MRI) &&
- "Must be able to replace dst with src!");
- I.eraseFromParent();
- MRI.replaceRegWith(DstReg, SrcReg);
- return true;
- }
case TargetOpcode::G_EXTRACT: {
Register DstReg = I.getOperand(0).getReg();
Register SrcReg = I.getOperand(1).getReg();
@@ -3031,7 +2974,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
if (isa<GStore>(LdSt) && ValTy.getSizeInBits() > MemSizeInBits) {
unsigned SubReg;
LLT MemTy = LdSt.getMMO().getMemoryType();
- auto *RC = getRegClassForTypeOnBank(MemTy, RB);
+ auto *RC = TRI.getRegClassForTypeOnBank(MemTy, RB);
if (!getSubRegForClass(RC, TRI, SubReg))
return false;
@@ -3047,7 +2990,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
if (RB.getID() == AArch64::FPRRegBankID) {
unsigned SubReg;
LLT MemTy = LdSt.getMMO().getMemoryType();
- auto *RC = getRegClassForTypeOnBank(MemTy, RB);
+ auto *RC = TRI.getRegClassForTypeOnBank(MemTy, RB);
if (!getSubRegForClass(RC, TRI, SubReg))
return false;
Register OldDst = LdSt.getReg(0);
@@ -3061,7 +3004,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
.addImm(0)
.addUse(NewDst)
.addImm(SubReg);
- auto SubRegRC = getRegClassForTypeOnBank(MRI.getType(OldDst), RB);
+ auto SubRegRC = TRI.getRegClassForTypeOnBank(MRI.getType(OldDst), RB);
RBI.constrainGenericRegister(OldDst, *SubRegRC, MRI);
MIB.setInstr(LdSt);
ValTy = MemTy; // This is no longer an extending load.
@@ -3251,11 +3194,13 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
}
if (DstRB.getID() == AArch64::GPRRegBankID) {
- const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
+ const TargetRegisterClass *DstRC =
+ TRI.getRegClassForTypeOnBank(DstTy, DstRB);
if (!DstRC)
return false;
- const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
+ const TargetRegisterClass *SrcRC =
+ TRI.getRegClassForTypeOnBank(SrcTy, SrcRB);
if (!SrcRC)
return false;
@@ -3548,7 +3493,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
const Register DstReg = I.getOperand(0).getReg();
const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
- const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
+ const TargetRegisterClass *DstRC =
+ TRI.getRegClassForTypeOnBank(DstTy, DstRB);
RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
return true;
}
@@ -3840,7 +3786,7 @@ AArch64InstructionSelector::emitNarrowVector(Register DstReg, Register SrcReg,
MachineRegisterInfo &MRI) const {
LLT DstTy = MRI.getType(DstReg);
const TargetRegisterClass *RC =
- getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(SrcReg, MRI, TRI));
+ TRI.getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(SrcReg, MRI, TRI));
if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
LLVM_DEBUG(dbgs() << "Unsupported register class!\n");
return nullptr;
@@ -3970,7 +3916,7 @@ MachineInstr *AArch64InstructionSelector::emitExtractVectorElt(
}
const TargetRegisterClass *DstRC =
- getRegClassForTypeOnBank(ScalarTy, DstRB, true);
+ TRI.getRegClassForTypeOnBank(ScalarTy, DstRB);
if (!DstRC) {
LLVM_DEBUG(dbgs() << "Could not determine destination register class.\n");
return nullptr;
@@ -3978,8 +3924,7 @@ MachineInstr *AArch64InstructionSelector::emitExtractVectorElt(
const RegisterBank &VecRB = *RBI.getRegBank(VecReg, MRI, TRI);
const LLT &VecTy = MRI.getType(VecReg);
- const TargetRegisterClass *VecRC =
- getRegClassForTypeOnBank(VecTy, VecRB, true);
+ const TargetRegisterClass *VecRC = TRI.getRegClassForTypeOnBank(VecTy, VecRB);
if (!VecRC) {
LLVM_DEBUG(dbgs() << "Could not determine source register class.\n");
return nullptr;
@@ -4139,7 +4084,7 @@ bool AArch64InstructionSelector::selectUnmergeValues(MachineInstr &I,
// For scalar sources, treat as a pseudo-vector of NarrowTy elements.
unsigned EltSize = WideTy.isVector() ? WideTy.getScalarSizeInBits()
: NarrowTy.getSizeInBits();
- const TargetRegisterClass *RC = getRegClassForTypeOnBank(
+ const TargetRegisterClass *RC = TRI.getRegClassForTypeOnBank(
LLT::fixed_vector(NumElts, EltSize), *RBI.getRegBank(SrcReg, MRI, TRI));
unsigned SubReg = 0;
bool Found = getSubRegForClass(RC, TRI, SubReg);
@@ -4600,7 +4545,7 @@ MachineInstr *AArch64InstructionSelector::emitVectorConcat(
const LLT ScalarTy = LLT::scalar(Op1Ty.getSizeInBits());
const RegisterBank &FPRBank = *RBI.getRegBank(Op1, MRI, TRI);
const TargetRegisterClass *DstRC =
- getRegClassForTypeOnBank(Op1Ty.multiplyElements(2), FPRBank);
+ TRI.getRegClassForTypeOnBank(Op1Ty.multiplyElements(2), FPRBank);
MachineInstr *WidenedOp1 =
emitScalarToVector(ScalarTy.getSizeInBits(), DstRC, Op1, MIRBuilder);
@@ -5582,8 +5527,8 @@ bool AArch64InstructionSelector::selectIndexedExtLoad(
.addImm(InsertIntoSubReg);
RBI.constrainGenericRegister(
SubToReg.getReg(0),
- *getRegClassForTypeOnBank(MRI.getType(Dst),
- *RBI.getRegBank(Dst, MRI, TRI)),
+ *TRI.getRegClassForTypeOnBank(MRI.getType(Dst),
+ *RBI.getRegBank(Dst, MRI, TRI)),
MRI);
} else {
auto Copy = MIB.buildCopy(Dst, LdMI.getReg(1));
@@ -5859,11 +5804,11 @@ bool AArch64InstructionSelector::tryOptBuildVecToSubregToReg(
}))
return false;
unsigned SubReg;
- const TargetRegisterClass *EltRC = getRegClassForTypeOnBank(EltTy, EltRB);
+ const TargetRegisterClass *EltRC = TRI.getRegClassForTypeOnBank(EltTy, EltRB);
if (!EltRC)
return false;
const TargetRegisterClass *DstRC =
- getRegClassForTypeOnBank(MRI.getType(Dst), DstRB);
+ TRI.getRegClassForTypeOnBank(MRI.getType(Dst), DstRB);
if (!DstRC)
return false;
if (!getSubRegForClass(EltRC, TRI, SubReg))
@@ -5924,7 +5869,7 @@ bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I,
if (DstSize < 128) {
// Force this to be FPR using the destination vector.
const TargetRegisterClass *RC =
- getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
+ TRI.getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
if (!RC)
return false;
if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
@@ -5966,8 +5911,8 @@ bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I,
Register DstReg = PrevMI->getOperand(0).getReg();
if (PrevMI == ScalarToVec && DstReg.isVirtual()) {
- const TargetRegisterClass *RC =
- getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
+ const TargetRegisterClass *RC = TRI.getRegClassForTypeOnBank(
+ DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
RBI.constrainGenericRegister(DstReg, *RC, MRI);
}
}
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 2e2916f68f584..62ed20c3fff8c 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -364,8 +364,9 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
const TargetRegisterClass *
getRegClassForSizeOnBank(unsigned Size, const RegisterBank &Bank) const;
- const TargetRegisterClass *
- getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank) const {
+ const TargetRegisterClass *getRegClassForTypeOnBank(
+ LLT Ty, const RegisterBank &Bank,
+ const TargetSubtargetInfo *STI = nullptr) const override {
return getRegClassForSizeOnBank(Ty.getSizeInBits(), Bank);
}
diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
index bd02b57bfc860..029f1c4a5cef9 100644
--- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
+++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
@@ -45,8 +45,6 @@ class MipsInstructionSelector : public InstructionSelector {
bool materialize32BitImm(Register DestReg, APInt Imm,
MachineIRBuilder &B) const;
bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
- const TargetRegisterClass *
- getRegClassForTypeOnBank(Register Reg, MachineRegisterInfo &MRI) const;
unsigned selectLoadStoreOpCode(MachineInstr &I,
MachineRegisterInfo &MRI) const;
bool buildUnalignedStore(MachineInstr &I, unsigned Opc,
@@ -108,7 +106,9 @@ bool MipsInstructionSelector::selectCopy(MachineInstr &I,
if (DstReg.isPhysical())
return true;
- const TargetRegisterClass *RC = getRegClassForTypeOnBank(DstReg, MRI);
+ const TargetRegisterClass *RC = TRI.getRegClassForTypeOnBank(
+ MRI.getType(DstReg), *RBI.getRegBank(DstReg, MRI, TRI),
+ &MF->getSubtarget());
if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
<< " operand\n");
@@ -117,34 +117,6 @@ bool MipsInstructionSelector::selectCopy(MachineInstr &I,
return true;
}
-const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
- Register Reg, MachineRegisterInfo &MRI) const {
- const LLT Ty = MRI.getType(Reg);
- const unsigned TySize = Ty.getSizeInBits();
-
- if (isRegInGprb(Reg, MRI)) {
- assert((Ty.isScalar() || Ty.isPointer()) &&
- (TySize == 32 || TySize == 64) &&
- "Register class not available for LLT, register bank combination");
- if (TySize == 32)
- return &Mips::GPR32RegClass;
- if (TySize == 64)
- return &Mips::GPR64RegClass;
- }
-
- if (isRegInFprb(Reg, MRI)) {
- if (Ty.isScalar()) {
- assert((TySize == 32 || TySize == 64) &&
- "Register class not available for LLT, register bank combination");
- if (TySize == 32)
- return &Mips::FGR32RegClass;
- return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
- }
- }
-
- llvm_unreachable("Unsupported register bank.");
-}
-
bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
MachineIRBuilder &B) const {
assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
@@ -428,7 +400,9 @@ bool MipsInstructionSelector::select(MachineInstr &I) {
if (DestReg.isPhysical())
DefRC = TRI.getRegClass(DestReg);
else
- DefRC = getRegClassForTypeOnBank(DestReg, MRI);
+ DefRC = TRI.getRegClassForTypeOnBank(MRI.getType(DestReg),
+ *RBI.getRegBank(DestReg, MRI, TRI),
+ &MF.getSubtarget());
I.setDesc(TII.get(TargetOpcode::PHI));
return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
@@ -576,7 +550,9 @@ bool MipsInstructionSelector::select(MachineInstr &I) {
.addDef(Dst);
// Set class based on register bank, there can be fpr and gpr implicit def.
- MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst, MRI));
+ MRI.setRegClass(Dst, TRI.getRegClassForTypeOnBank(
+ MRI.getType(Dst), *RBI.getRegBank(Dst, MRI, TRI),
+ &MF.getSubtarget()));
break;
}
case G_CONSTANT: {
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index 948d4db8585db..288224a6f2284 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -14,6 +14,7 @@
#include "MCTargetDesc/MipsABIInfo.h"
#include "Mips.h"
#include "MipsMachineFunction.h"
+#include "MipsRegisterBankInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/BitVector.h"
@@ -319,3 +320,33 @@ bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
// sized objects.
return MF.getRegInfo().canReserveReg(BP);
}
+
+const TargetRegisterClass *MipsRegisterInfo::getRegClassForTypeOnBank(
+ LLT Ty, const RegisterBank &RB, const TargetSubtargetInfo *STI) const {
+ const unsigned TySize = Ty.getSizeInBits();
+
+ if (RB.getID() == Mips::GPRBRegBankID) {
+ assert((Ty.isScalar() || Ty.isPointer()) &&
+ (TySize == 32 || TySize == 64) &&
+ "Register class not available for LLT, register bank combination");
+ if (TySize == 32)
+ return &Mips::GPR32RegClass;
+ if (TySize == 64)
+ return &Mips::GPR64RegClass;
+ }
+
+ if (RB.getID() == Mips::FPRBRegBankID) {
+ if (Ty.isScalar()) {
+ assert((TySize == 32 || TySize == 64) &&
+ "Register class not available for LLT, register bank combination");
+ if (TySize == 32)
+ return &Mips::FGR32RegClass;
+ assert(STI != nullptr);
+ return static_cast<const MipsSubtarget *>(STI)->isFP64bit()
+ ? &Mips::FGR64RegClass
+ : &Mips::AFGR64RegClass;
+ }
+ }
+
+ llvm_unreachable("Unsupported register bank.");
+}
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.h b/llvm/lib/Target/Mips/MipsRegisterInfo.h
index e2e81af4a8af1..39c86b5ec16f9 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.h
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.h
@@ -60,6 +60,10 @@ class MipsRegisterInfo : public MipsGenRegisterInfo {
/// Return GPR register class.
virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0;
+ const TargetRegisterClass *
+ getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank,
+ const TargetSubtargetInfo *STI) const override;
+
private:
virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
int FrameIndex, uint64_t StackSize,
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 8769bb2238980..51a3c7b3a7a97 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -54,9 +54,6 @@ class RISCVInstructionSelector : public InstructionSelector {
static const char *getName() { return DEBUG_TYPE; }
private:
- const TargetRegisterClass *
- getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) const;
-
static constexpr unsigned MaxRecursionDepth = 6;
bool hasAllNBitUsers(const MachineInstr &MI, unsigned Bits,
@@ -1105,7 +1102,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
}
const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
- DefRC = getRegClassForTypeOnBank(DefTy, RB);
+ DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB, &MF->getSubtarget());
if (!DefRC) {
LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
return false;
@@ -1506,39 +1503,6 @@ void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
MIB.addImm(Imm);
}
-const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
- LLT Ty, const RegisterBank &RB) const {
- if (RB.getID() == RISCV::GPRBRegBankID) {
- if (Ty.getSizeInBits() <= 32 || (STI.is64Bit() && Ty.getSizeInBits() == 64))
- return &RISCV::GPRRegClass;
- }
-
- if (RB.getID() == RISCV::FPRBRegBankID) {
- if (Ty.getSizeInBits() == 16)
- return &RISCV::FPR16RegClass;
- if (Ty.getSizeInBits() == 32)
- return &RISCV::FPR32RegClass;
- if (Ty.getSizeInBits() == 64)
- return &RISCV::FPR64RegClass;
- }
-
- if (RB.getID() == RISCV::VRBRegBankID) {
- if (Ty.getSizeInBits().getKnownMinValue() <= 64)
- return &RISCV::VRRegClass;
-
- if (Ty.getSizeInBits().getKnownMinValue() == 128)
- return &RISCV::VRM2RegClass;
-
- if (Ty.getSizeInBits().getKnownMinValue() == 256)
- return &RISCV::VRM4RegClass;
-
- if (Ty.getSizeInBits().getKnownMinValue() == 512)
- return &RISCV::VRM8RegClass;
- }
-
- return nullptr;
-}
-
bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
}
@@ -1553,8 +1517,9 @@ bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
if (DstReg.isPhysical())
return true;
- const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
- MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
+ const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
+ MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI),
+ &MF->getSubtarget());
assert(DstRC &&
"Register class not available for LLT, register bank combination");
@@ -1576,8 +1541,9 @@ bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI,
assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
const Register DstReg = MI.getOperand(0).getReg();
- const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
- MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
+ const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
+ MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI),
+ &MF->getSubtarget());
assert(DstRC &&
"Register class not available for LLT, register bank combination");
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 0770935b749d9..d764eace00800 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "RISCVRegisterInfo.h"
+#include "GISel/RISCVRegisterBankInfo.h"
#include "RISCV.h"
#include "RISCVSubtarget.h"
#include "llvm/ADT/SmallSet.h"
@@ -1091,3 +1092,39 @@ RISCVRegisterInfo::findVRegWithEncoding(const TargetRegisterClass &RegClass,
return Reg;
return getMatchingSuperReg(Reg, RISCV::sub_vrm1_0, &RegClass);
}
+
+const TargetRegisterClass *RISCVRegisterInfo::getRegClassForTypeOnBank(
+ LLT Ty, const RegisterBank &RB, const TargetSubtargetInfo *STI) const {
+ assert(STI != nullptr);
+ if (RB.getID() == RISCV::GPRBRegBankID) {
+ if (Ty.getSizeInBits() <= 32 ||
+ (static_cast<const RISCVSubtarget *>(STI)->is64Bit() &&
+ Ty.getSizeInBits() == 64))
+ return &RISCV::GPRRegClass;
+ }
+
+ if (RB.getID() == RISCV::FPRBRegBankID) {
+ if (Ty.getSizeInBits() == 16)
+ return &RISCV::FPR16RegClass;
+ if (Ty.getSizeInBits() == 32)
+ return &RISCV::FPR32RegClass;
+ if (Ty.getSizeInBits() == 64)
+ return &RISCV::FPR64RegClass;
+ }
+
+ if (RB.getID() == RISCV::VRBRegBankID) {
+ if (Ty.getSizeInBits().getKnownMinValue() <= 64)
+ return &RISCV::VRRegClass;
+
+ if (Ty.getSizeInBits().getKnownMinValue() == 128)
+ return &RISCV::VRM2RegClass;
+
+ if (Ty.getSizeInBits().getKnownMinValue() == 256)
+ return &RISCV::VRM4RegClass;
+
+ if (Ty.getSizeInBits().getKnownMinValue() == 512)
+ return &RISCV::VRM8RegClass;
+ }
+
+ return nullptr;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
index f29f85e4987f6..d98240447454c 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
@@ -168,6 +168,10 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
static bool isRVVRegClass(const TargetRegisterClass *RC) {
return RISCVRI::isVRegClass(RC->TSFlags);
}
+
+ const TargetRegisterClass *
+ getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank,
+ const TargetSubtargetInfo *STI) const override;
};
} // namespace llvm
>From 626eeb89624e56f0009cd0ab1500eb2d73260c11 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Thu, 29 Jan 2026 10:48:12 +0000
Subject: [PATCH 4/6] Revert "move fix to generic selection"
This reverts commit 12e2fa2827e1ed1ce1d72134f807b659da28a402.
---
.../include/llvm/CodeGen/TargetRegisterInfo.h | 9 --
.../CodeGen/GlobalISel/InstructionSelect.cpp | 21 ++--
.../Target/AArch64/AArch64RegisterInfo.cpp | 34 ------
llvm/lib/Target/AArch64/AArch64RegisterInfo.h | 4 -
.../GISel/AArch64InstructionSelector.cpp | 111 +++++++++++++-----
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 5 +-
.../Target/Mips/MipsInstructionSelector.cpp | 42 +++++--
llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 31 -----
llvm/lib/Target/Mips/MipsRegisterInfo.h | 4 -
.../RISCV/GISel/RISCVInstructionSelector.cpp | 48 ++++++--
llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 37 ------
llvm/lib/Target/RISCV/RISCVRegisterInfo.h | 4 -
12 files changed, 167 insertions(+), 183 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 2fbbe0ee0932e..35b14e8b8fd30 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -21,7 +21,6 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/RegisterBank.h"
-#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -383,14 +382,6 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
const TargetRegisterClass *
getAllocatableClass(const TargetRegisterClass *RC) const;
- /// Given a register bank, and a type, return the smallest register class
- /// that can represent that combination.
- virtual const TargetRegisterClass *
- getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank,
- const TargetSubtargetInfo *STI = nullptr) const {
- return nullptr;
- }
-
/// Returns a bitset indexed by register number indicating if a register is
/// allocatable or not. If a register class is specified, returns the subset
/// for the class.
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index c689413cc1293..4b1a8a34ab3fc 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -23,7 +23,6 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -357,21 +356,17 @@ bool InstructionSelect::selectInstr(MachineInstr &MI) {
return true;
}
- // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
+ if (MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
+ // Allow targets to provide custom handling before falling back to the
+ // generic elimination below.
+ if (ISel->select(MI))
+ return true;
+ }
+
+ // Eliminate hints or a remaining G_CONSTANT_FOLD_BARRIER.
if (isPreISelGenericOptimizationHint(MI.getOpcode()) ||
MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
- const RegisterBankInfo *RBI = ISel->MF->getSubtarget().getRegBankInfo();
- const TargetRegisterInfo *TRI = ISel->MF->getSubtarget().getRegisterInfo();
- auto ConstrainToRC = [&](Register Reg) {
- const RegisterBank *RB = RBI->getRegBank(Reg, MRI, *TRI);
- const TargetRegisterClass *RC = TRI->getRegClassForTypeOnBank(
- MRI.getType(Reg), *RB, &ISel->MF->getSubtarget());
- return !RC || (RC && RBI->constrainGenericRegister(Reg, *RC, MRI));
- };
-
auto [DstReg, SrcReg] = MI.getFirst2Regs();
- if (!ConstrainToRC(DstReg) || !ConstrainToRC(SrcReg))
- return false;
// At this point, the destination register class of the op may have
// been decided.
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index 86003693973a8..8c0dd4381fae8 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -17,7 +17,6 @@
#include "AArch64MachineFunctionInfo.h"
#include "AArch64SMEAttributes.h"
#include "AArch64Subtarget.h"
-#include "GISel/AArch64RegisterBankInfo.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "MCTargetDesc/AArch64InstPrinter.h"
#include "llvm/ADT/BitVector.h"
@@ -1443,36 +1442,3 @@ bool AArch64RegisterInfo::isIgnoredCVReg(MCRegister LLVMReg) const {
return (LLVMReg >= AArch64::Z0 && LLVMReg <= AArch64::Z31) ||
(LLVMReg >= AArch64::P0 && LLVMReg <= AArch64::P15);
}
-
-// FIXME: This should be target-independent, inferred from the types declared
-// for each class in the bank.
-const TargetRegisterClass *AArch64RegisterInfo::getRegClassForTypeOnBank(
- LLT Ty, const RegisterBank &RB, const TargetSubtargetInfo *STI) const {
- if (RB.getID() == AArch64::GPRRegBankID) {
- if (Ty.getSizeInBits() <= 32)
- return &AArch64::GPR32RegClass;
- if (Ty.getSizeInBits() == 64)
- return &AArch64::GPR64RegClass;
- if (Ty.getSizeInBits() == 128)
- return &AArch64::XSeqPairsClassRegClass;
- return nullptr;
- }
-
- if (RB.getID() == AArch64::FPRRegBankID) {
- switch (Ty.getSizeInBits()) {
- case 8:
- return &AArch64::FPR8RegClass;
- case 16:
- return &AArch64::FPR16RegClass;
- case 32:
- return &AArch64::FPR32RegClass;
- case 64:
- return &AArch64::FPR64RegClass;
- case 128:
- return &AArch64::FPR128RegClass;
- }
- return nullptr;
- }
-
- return nullptr;
-}
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
index 7ce922aee3f97..89d1802ab98d5 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h
@@ -154,10 +154,6 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
bool shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const override;
bool isIgnoredCVReg(MCRegister LLVMReg) const override;
-
- const TargetRegisterClass *getRegClassForTypeOnBank(
- LLT Ty, const RegisterBank &Bank,
- const TargetSubtargetInfo *STI = nullptr) const override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 46d1d2c1029bd..36e2c689aba13 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -564,6 +564,45 @@ AArch64InstructionSelector::AArch64InstructionSelector(
{
}
+// FIXME: This should be target-independent, inferred from the types declared
+// for each class in the bank.
+//
+/// Given a register bank, and a type, return the smallest register class that
+/// can represent that combination.
+static const TargetRegisterClass *
+getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB,
+ bool GetAllRegSet = false) {
+ if (RB.getID() == AArch64::GPRRegBankID) {
+ if (Ty.getSizeInBits() <= 32)
+ return GetAllRegSet ? &AArch64::GPR32allRegClass
+ : &AArch64::GPR32RegClass;
+ if (Ty.getSizeInBits() == 64)
+ return GetAllRegSet ? &AArch64::GPR64allRegClass
+ : &AArch64::GPR64RegClass;
+ if (Ty.getSizeInBits() == 128)
+ return &AArch64::XSeqPairsClassRegClass;
+ return nullptr;
+ }
+
+ if (RB.getID() == AArch64::FPRRegBankID) {
+ switch (Ty.getSizeInBits()) {
+ case 8:
+ return &AArch64::FPR8RegClass;
+ case 16:
+ return &AArch64::FPR16RegClass;
+ case 32:
+ return &AArch64::FPR32RegClass;
+ case 64:
+ return &AArch64::FPR64RegClass;
+ case 128:
+ return &AArch64::FPR128RegClass;
+ }
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
/// Given a register bank, and size in bits, return the smallest register class
/// that can represent that combination.
static const TargetRegisterClass *
@@ -961,9 +1000,7 @@ static bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI,
dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
if (!RC) {
const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
- const TargetRegisterInfo *TRI =
- I.getMF()->getSubtarget().getRegisterInfo();
- RC = TRI->getRegClassForTypeOnBank(Ty, RB);
+ RC = getRegClassForTypeOnBank(Ty, RB);
if (!RC) {
LLVM_DEBUG(
dbgs() << "Warning: DBG_VALUE operand has unexpected size/bank\n");
@@ -1867,7 +1904,7 @@ bool AArch64InstructionSelector::selectVectorAshrLshr(
unsigned Opc = 0;
unsigned NegOpc = 0;
const TargetRegisterClass *RC =
- TRI.getRegClassForTypeOnBank(Ty, RBI.getRegBank(AArch64::FPRRegBankID));
+ getRegClassForTypeOnBank(Ty, RBI.getRegBank(AArch64::FPRRegBankID));
if (Ty == LLT::fixed_vector(2, 64)) {
Opc = IsASHR ? AArch64::SSHLv2i64 : AArch64::USHLv2i64;
NegOpc = AArch64::NEGv2i64;
@@ -2506,7 +2543,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
return false;
}
const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
- DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
+ DefRC = getRegClassForTypeOnBank(DefTy, RB);
if (!DefRC) {
LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
return false;
@@ -2680,8 +2717,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
}
if (isFP) {
- const TargetRegisterClass &FPRRC =
- *TRI.getRegClassForTypeOnBank(DefTy, RB);
+ const TargetRegisterClass &FPRRC = *getRegClassForTypeOnBank(DefTy, RB);
// For 16, 64, and 128b values, emit a constant pool load.
switch (DefSize) {
default:
@@ -2743,6 +2779,27 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
return true;
}
+ case TargetOpcode::G_CONSTANT_FOLD_BARRIER: {
+ auto ConstrainToRC = [&](Register Reg) {
+ const RegisterBank &RB = *RBI.getRegBank(Reg, MRI, TRI);
+ const TargetRegisterClass *RC =
+ getRegClassForTypeOnBank(MRI.getType(Reg), RB);
+ return RC && RBI.constrainGenericRegister(Reg, *RC, MRI);
+ };
+
+ auto [DstReg, SrcReg] = I.getFirst2Regs();
+ if (!ConstrainToRC(DstReg) || !ConstrainToRC(SrcReg))
+ return false;
+
+ if (const auto *DstRC = MRI.getRegClassOrNull(DstReg))
+ MRI.setRegClass(SrcReg, DstRC);
+
+ assert(canReplaceReg(DstReg, SrcReg, MRI) &&
+ "Must be able to replace dst with src!");
+ I.eraseFromParent();
+ MRI.replaceRegWith(DstReg, SrcReg);
+ return true;
+ }
case TargetOpcode::G_EXTRACT: {
Register DstReg = I.getOperand(0).getReg();
Register SrcReg = I.getOperand(1).getReg();
@@ -2974,7 +3031,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
if (isa<GStore>(LdSt) && ValTy.getSizeInBits() > MemSizeInBits) {
unsigned SubReg;
LLT MemTy = LdSt.getMMO().getMemoryType();
- auto *RC = TRI.getRegClassForTypeOnBank(MemTy, RB);
+ auto *RC = getRegClassForTypeOnBank(MemTy, RB);
if (!getSubRegForClass(RC, TRI, SubReg))
return false;
@@ -2990,7 +3047,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
if (RB.getID() == AArch64::FPRRegBankID) {
unsigned SubReg;
LLT MemTy = LdSt.getMMO().getMemoryType();
- auto *RC = TRI.getRegClassForTypeOnBank(MemTy, RB);
+ auto *RC = getRegClassForTypeOnBank(MemTy, RB);
if (!getSubRegForClass(RC, TRI, SubReg))
return false;
Register OldDst = LdSt.getReg(0);
@@ -3004,7 +3061,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
.addImm(0)
.addUse(NewDst)
.addImm(SubReg);
- auto SubRegRC = TRI.getRegClassForTypeOnBank(MRI.getType(OldDst), RB);
+ auto SubRegRC = getRegClassForTypeOnBank(MRI.getType(OldDst), RB);
RBI.constrainGenericRegister(OldDst, *SubRegRC, MRI);
MIB.setInstr(LdSt);
ValTy = MemTy; // This is no longer an extending load.
@@ -3194,13 +3251,11 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
}
if (DstRB.getID() == AArch64::GPRRegBankID) {
- const TargetRegisterClass *DstRC =
- TRI.getRegClassForTypeOnBank(DstTy, DstRB);
+ const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
if (!DstRC)
return false;
- const TargetRegisterClass *SrcRC =
- TRI.getRegClassForTypeOnBank(SrcTy, SrcRB);
+ const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
if (!SrcRC)
return false;
@@ -3493,8 +3548,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
const Register DstReg = I.getOperand(0).getReg();
const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
- const TargetRegisterClass *DstRC =
- TRI.getRegClassForTypeOnBank(DstTy, DstRB);
+ const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
return true;
}
@@ -3786,7 +3840,7 @@ AArch64InstructionSelector::emitNarrowVector(Register DstReg, Register SrcReg,
MachineRegisterInfo &MRI) const {
LLT DstTy = MRI.getType(DstReg);
const TargetRegisterClass *RC =
- TRI.getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(SrcReg, MRI, TRI));
+ getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(SrcReg, MRI, TRI));
if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
LLVM_DEBUG(dbgs() << "Unsupported register class!\n");
return nullptr;
@@ -3916,7 +3970,7 @@ MachineInstr *AArch64InstructionSelector::emitExtractVectorElt(
}
const TargetRegisterClass *DstRC =
- TRI.getRegClassForTypeOnBank(ScalarTy, DstRB);
+ getRegClassForTypeOnBank(ScalarTy, DstRB, true);
if (!DstRC) {
LLVM_DEBUG(dbgs() << "Could not determine destination register class.\n");
return nullptr;
@@ -3924,7 +3978,8 @@ MachineInstr *AArch64InstructionSelector::emitExtractVectorElt(
const RegisterBank &VecRB = *RBI.getRegBank(VecReg, MRI, TRI);
const LLT &VecTy = MRI.getType(VecReg);
- const TargetRegisterClass *VecRC = TRI.getRegClassForTypeOnBank(VecTy, VecRB);
+ const TargetRegisterClass *VecRC =
+ getRegClassForTypeOnBank(VecTy, VecRB, true);
if (!VecRC) {
LLVM_DEBUG(dbgs() << "Could not determine source register class.\n");
return nullptr;
@@ -4084,7 +4139,7 @@ bool AArch64InstructionSelector::selectUnmergeValues(MachineInstr &I,
// For scalar sources, treat as a pseudo-vector of NarrowTy elements.
unsigned EltSize = WideTy.isVector() ? WideTy.getScalarSizeInBits()
: NarrowTy.getSizeInBits();
- const TargetRegisterClass *RC = TRI.getRegClassForTypeOnBank(
+ const TargetRegisterClass *RC = getRegClassForTypeOnBank(
LLT::fixed_vector(NumElts, EltSize), *RBI.getRegBank(SrcReg, MRI, TRI));
unsigned SubReg = 0;
bool Found = getSubRegForClass(RC, TRI, SubReg);
@@ -4545,7 +4600,7 @@ MachineInstr *AArch64InstructionSelector::emitVectorConcat(
const LLT ScalarTy = LLT::scalar(Op1Ty.getSizeInBits());
const RegisterBank &FPRBank = *RBI.getRegBank(Op1, MRI, TRI);
const TargetRegisterClass *DstRC =
- TRI.getRegClassForTypeOnBank(Op1Ty.multiplyElements(2), FPRBank);
+ getRegClassForTypeOnBank(Op1Ty.multiplyElements(2), FPRBank);
MachineInstr *WidenedOp1 =
emitScalarToVector(ScalarTy.getSizeInBits(), DstRC, Op1, MIRBuilder);
@@ -5527,8 +5582,8 @@ bool AArch64InstructionSelector::selectIndexedExtLoad(
.addImm(InsertIntoSubReg);
RBI.constrainGenericRegister(
SubToReg.getReg(0),
- *TRI.getRegClassForTypeOnBank(MRI.getType(Dst),
- *RBI.getRegBank(Dst, MRI, TRI)),
+ *getRegClassForTypeOnBank(MRI.getType(Dst),
+ *RBI.getRegBank(Dst, MRI, TRI)),
MRI);
} else {
auto Copy = MIB.buildCopy(Dst, LdMI.getReg(1));
@@ -5804,11 +5859,11 @@ bool AArch64InstructionSelector::tryOptBuildVecToSubregToReg(
}))
return false;
unsigned SubReg;
- const TargetRegisterClass *EltRC = TRI.getRegClassForTypeOnBank(EltTy, EltRB);
+ const TargetRegisterClass *EltRC = getRegClassForTypeOnBank(EltTy, EltRB);
if (!EltRC)
return false;
const TargetRegisterClass *DstRC =
- TRI.getRegClassForTypeOnBank(MRI.getType(Dst), DstRB);
+ getRegClassForTypeOnBank(MRI.getType(Dst), DstRB);
if (!DstRC)
return false;
if (!getSubRegForClass(EltRC, TRI, SubReg))
@@ -5869,7 +5924,7 @@ bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I,
if (DstSize < 128) {
// Force this to be FPR using the destination vector.
const TargetRegisterClass *RC =
- TRI.getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
+ getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
if (!RC)
return false;
if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
@@ -5911,8 +5966,8 @@ bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I,
Register DstReg = PrevMI->getOperand(0).getReg();
if (PrevMI == ScalarToVec && DstReg.isVirtual()) {
- const TargetRegisterClass *RC = TRI.getRegClassForTypeOnBank(
- DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
+ const TargetRegisterClass *RC =
+ getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
RBI.constrainGenericRegister(DstReg, *RC, MRI);
}
}
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 62ed20c3fff8c..2e2916f68f584 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -364,9 +364,8 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
const TargetRegisterClass *
getRegClassForSizeOnBank(unsigned Size, const RegisterBank &Bank) const;
- const TargetRegisterClass *getRegClassForTypeOnBank(
- LLT Ty, const RegisterBank &Bank,
- const TargetSubtargetInfo *STI = nullptr) const override {
+ const TargetRegisterClass *
+ getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank) const {
return getRegClassForSizeOnBank(Ty.getSizeInBits(), Bank);
}
diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
index 029f1c4a5cef9..bd02b57bfc860 100644
--- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
+++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
@@ -45,6 +45,8 @@ class MipsInstructionSelector : public InstructionSelector {
bool materialize32BitImm(Register DestReg, APInt Imm,
MachineIRBuilder &B) const;
bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
+ const TargetRegisterClass *
+ getRegClassForTypeOnBank(Register Reg, MachineRegisterInfo &MRI) const;
unsigned selectLoadStoreOpCode(MachineInstr &I,
MachineRegisterInfo &MRI) const;
bool buildUnalignedStore(MachineInstr &I, unsigned Opc,
@@ -106,9 +108,7 @@ bool MipsInstructionSelector::selectCopy(MachineInstr &I,
if (DstReg.isPhysical())
return true;
- const TargetRegisterClass *RC = TRI.getRegClassForTypeOnBank(
- MRI.getType(DstReg), *RBI.getRegBank(DstReg, MRI, TRI),
- &MF->getSubtarget());
+ const TargetRegisterClass *RC = getRegClassForTypeOnBank(DstReg, MRI);
if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
<< " operand\n");
@@ -117,6 +117,34 @@ bool MipsInstructionSelector::selectCopy(MachineInstr &I,
return true;
}
+const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
+ Register Reg, MachineRegisterInfo &MRI) const {
+ const LLT Ty = MRI.getType(Reg);
+ const unsigned TySize = Ty.getSizeInBits();
+
+ if (isRegInGprb(Reg, MRI)) {
+ assert((Ty.isScalar() || Ty.isPointer()) &&
+ (TySize == 32 || TySize == 64) &&
+ "Register class not available for LLT, register bank combination");
+ if (TySize == 32)
+ return &Mips::GPR32RegClass;
+ if (TySize == 64)
+ return &Mips::GPR64RegClass;
+ }
+
+ if (isRegInFprb(Reg, MRI)) {
+ if (Ty.isScalar()) {
+ assert((TySize == 32 || TySize == 64) &&
+ "Register class not available for LLT, register bank combination");
+ if (TySize == 32)
+ return &Mips::FGR32RegClass;
+ return STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
+ }
+ }
+
+ llvm_unreachable("Unsupported register bank.");
+}
+
bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
MachineIRBuilder &B) const {
assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
@@ -400,9 +428,7 @@ bool MipsInstructionSelector::select(MachineInstr &I) {
if (DestReg.isPhysical())
DefRC = TRI.getRegClass(DestReg);
else
- DefRC = TRI.getRegClassForTypeOnBank(MRI.getType(DestReg),
- *RBI.getRegBank(DestReg, MRI, TRI),
- &MF.getSubtarget());
+ DefRC = getRegClassForTypeOnBank(DestReg, MRI);
I.setDesc(TII.get(TargetOpcode::PHI));
return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
@@ -550,9 +576,7 @@ bool MipsInstructionSelector::select(MachineInstr &I) {
.addDef(Dst);
// Set class based on register bank, there can be fpr and gpr implicit def.
- MRI.setRegClass(Dst, TRI.getRegClassForTypeOnBank(
- MRI.getType(Dst), *RBI.getRegBank(Dst, MRI, TRI),
- &MF.getSubtarget()));
+ MRI.setRegClass(Dst, getRegClassForTypeOnBank(Dst, MRI));
break;
}
case G_CONSTANT: {
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index 288224a6f2284..948d4db8585db 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -14,7 +14,6 @@
#include "MCTargetDesc/MipsABIInfo.h"
#include "Mips.h"
#include "MipsMachineFunction.h"
-#include "MipsRegisterBankInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/BitVector.h"
@@ -320,33 +319,3 @@ bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
// sized objects.
return MF.getRegInfo().canReserveReg(BP);
}
-
-const TargetRegisterClass *MipsRegisterInfo::getRegClassForTypeOnBank(
- LLT Ty, const RegisterBank &RB, const TargetSubtargetInfo *STI) const {
- const unsigned TySize = Ty.getSizeInBits();
-
- if (RB.getID() == Mips::GPRBRegBankID) {
- assert((Ty.isScalar() || Ty.isPointer()) &&
- (TySize == 32 || TySize == 64) &&
- "Register class not available for LLT, register bank combination");
- if (TySize == 32)
- return &Mips::GPR32RegClass;
- if (TySize == 64)
- return &Mips::GPR64RegClass;
- }
-
- if (RB.getID() == Mips::FPRBRegBankID) {
- if (Ty.isScalar()) {
- assert((TySize == 32 || TySize == 64) &&
- "Register class not available for LLT, register bank combination");
- if (TySize == 32)
- return &Mips::FGR32RegClass;
- assert(STI != nullptr);
- return static_cast<const MipsSubtarget *>(STI)->isFP64bit()
- ? &Mips::FGR64RegClass
- : &Mips::AFGR64RegClass;
- }
- }
-
- llvm_unreachable("Unsupported register bank.");
-}
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.h b/llvm/lib/Target/Mips/MipsRegisterInfo.h
index 39c86b5ec16f9..e2e81af4a8af1 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.h
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.h
@@ -60,10 +60,6 @@ class MipsRegisterInfo : public MipsGenRegisterInfo {
/// Return GPR register class.
virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0;
- const TargetRegisterClass *
- getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank,
- const TargetSubtargetInfo *STI) const override;
-
private:
virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
int FrameIndex, uint64_t StackSize,
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 51a3c7b3a7a97..8769bb2238980 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -54,6 +54,9 @@ class RISCVInstructionSelector : public InstructionSelector {
static const char *getName() { return DEBUG_TYPE; }
private:
+ const TargetRegisterClass *
+ getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) const;
+
static constexpr unsigned MaxRecursionDepth = 6;
bool hasAllNBitUsers(const MachineInstr &MI, unsigned Bits,
@@ -1102,7 +1105,7 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
}
const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
- DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB, &MF->getSubtarget());
+ DefRC = getRegClassForTypeOnBank(DefTy, RB);
if (!DefRC) {
LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
return false;
@@ -1503,6 +1506,39 @@ void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
MIB.addImm(Imm);
}
+const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
+ LLT Ty, const RegisterBank &RB) const {
+ if (RB.getID() == RISCV::GPRBRegBankID) {
+ if (Ty.getSizeInBits() <= 32 || (STI.is64Bit() && Ty.getSizeInBits() == 64))
+ return &RISCV::GPRRegClass;
+ }
+
+ if (RB.getID() == RISCV::FPRBRegBankID) {
+ if (Ty.getSizeInBits() == 16)
+ return &RISCV::FPR16RegClass;
+ if (Ty.getSizeInBits() == 32)
+ return &RISCV::FPR32RegClass;
+ if (Ty.getSizeInBits() == 64)
+ return &RISCV::FPR64RegClass;
+ }
+
+ if (RB.getID() == RISCV::VRBRegBankID) {
+ if (Ty.getSizeInBits().getKnownMinValue() <= 64)
+ return &RISCV::VRRegClass;
+
+ if (Ty.getSizeInBits().getKnownMinValue() == 128)
+ return &RISCV::VRM2RegClass;
+
+ if (Ty.getSizeInBits().getKnownMinValue() == 256)
+ return &RISCV::VRM4RegClass;
+
+ if (Ty.getSizeInBits().getKnownMinValue() == 512)
+ return &RISCV::VRM8RegClass;
+ }
+
+ return nullptr;
+}
+
bool RISCVInstructionSelector::isRegInGprb(Register Reg) const {
return RBI.getRegBank(Reg, *MRI, TRI)->getID() == RISCV::GPRBRegBankID;
}
@@ -1517,9 +1553,8 @@ bool RISCVInstructionSelector::selectCopy(MachineInstr &MI) const {
if (DstReg.isPhysical())
return true;
- const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
- MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI),
- &MF->getSubtarget());
+ const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
+ MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
assert(DstRC &&
"Register class not available for LLT, register bank combination");
@@ -1541,9 +1576,8 @@ bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &MI,
assert(MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
const Register DstReg = MI.getOperand(0).getReg();
- const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(
- MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI),
- &MF->getSubtarget());
+ const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
+ MRI->getType(DstReg), *RBI.getRegBank(DstReg, *MRI, TRI));
assert(DstRC &&
"Register class not available for LLT, register bank combination");
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index d764eace00800..0770935b749d9 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//
#include "RISCVRegisterInfo.h"
-#include "GISel/RISCVRegisterBankInfo.h"
#include "RISCV.h"
#include "RISCVSubtarget.h"
#include "llvm/ADT/SmallSet.h"
@@ -1092,39 +1091,3 @@ RISCVRegisterInfo::findVRegWithEncoding(const TargetRegisterClass &RegClass,
return Reg;
return getMatchingSuperReg(Reg, RISCV::sub_vrm1_0, &RegClass);
}
-
-const TargetRegisterClass *RISCVRegisterInfo::getRegClassForTypeOnBank(
- LLT Ty, const RegisterBank &RB, const TargetSubtargetInfo *STI) const {
- assert(STI != nullptr);
- if (RB.getID() == RISCV::GPRBRegBankID) {
- if (Ty.getSizeInBits() <= 32 ||
- (static_cast<const RISCVSubtarget *>(STI)->is64Bit() &&
- Ty.getSizeInBits() == 64))
- return &RISCV::GPRRegClass;
- }
-
- if (RB.getID() == RISCV::FPRBRegBankID) {
- if (Ty.getSizeInBits() == 16)
- return &RISCV::FPR16RegClass;
- if (Ty.getSizeInBits() == 32)
- return &RISCV::FPR32RegClass;
- if (Ty.getSizeInBits() == 64)
- return &RISCV::FPR64RegClass;
- }
-
- if (RB.getID() == RISCV::VRBRegBankID) {
- if (Ty.getSizeInBits().getKnownMinValue() <= 64)
- return &RISCV::VRRegClass;
-
- if (Ty.getSizeInBits().getKnownMinValue() == 128)
- return &RISCV::VRM2RegClass;
-
- if (Ty.getSizeInBits().getKnownMinValue() == 256)
- return &RISCV::VRM4RegClass;
-
- if (Ty.getSizeInBits().getKnownMinValue() == 512)
- return &RISCV::VRM8RegClass;
- }
-
- return nullptr;
-}
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
index d98240447454c..f29f85e4987f6 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
@@ -168,10 +168,6 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
static bool isRVVRegClass(const TargetRegisterClass *RC) {
return RISCVRI::isVRegClass(RC->TSFlags);
}
-
- const TargetRegisterClass *
- getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank,
- const TargetSubtargetInfo *STI) const override;
};
} // namespace llvm
>From 766e2707582559b3d978c7a4cd4451d81f13a59a Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Fri, 30 Jan 2026 11:22:36 +0000
Subject: [PATCH 5/6] address comments
---
.../CodeGen/GlobalISel/InstructionSelect.cpp | 16 +++++---------
.../GISel/AArch64InstructionSelector.cpp | 21 -------------------
2 files changed, 5 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index 4b1a8a34ab3fc..5fb31a04e5fd0 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -356,14 +356,7 @@ bool InstructionSelect::selectInstr(MachineInstr &MI) {
return true;
}
- if (MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
- // Allow targets to provide custom handling before falling back to the
- // generic elimination below.
- if (ISel->select(MI))
- return true;
- }
-
- // Eliminate hints or a remaining G_CONSTANT_FOLD_BARRIER.
+ // Eliminate hints or G_CONSTANT_FOLD_BARRIER.
if (isPreISelGenericOptimizationHint(MI.getOpcode()) ||
MI.getOpcode() == TargetOpcode::G_CONSTANT_FOLD_BARRIER) {
auto [DstReg, SrcReg] = MI.getFirst2Regs();
@@ -373,10 +366,11 @@ bool InstructionSelect::selectInstr(MachineInstr &MI) {
//
// Propagate that through to the source register.
const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
- if (DstRC)
+ const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg);
+ if (DstRC && SrcRC)
+ MRI.constrainRegClass(SrcReg, DstRC);
+ else if (DstRC)
MRI.setRegClass(SrcReg, DstRC);
- assert(canReplaceReg(DstReg, SrcReg, MRI) &&
- "Must be able to replace dst with src!");
MI.eraseFromParent();
MRI.replaceRegWith(DstReg, SrcReg);
return true;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 36e2c689aba13..7605bbea51f56 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2779,27 +2779,6 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
return true;
}
- case TargetOpcode::G_CONSTANT_FOLD_BARRIER: {
- auto ConstrainToRC = [&](Register Reg) {
- const RegisterBank &RB = *RBI.getRegBank(Reg, MRI, TRI);
- const TargetRegisterClass *RC =
- getRegClassForTypeOnBank(MRI.getType(Reg), RB);
- return RC && RBI.constrainGenericRegister(Reg, *RC, MRI);
- };
-
- auto [DstReg, SrcReg] = I.getFirst2Regs();
- if (!ConstrainToRC(DstReg) || !ConstrainToRC(SrcReg))
- return false;
-
- if (const auto *DstRC = MRI.getRegClassOrNull(DstReg))
- MRI.setRegClass(SrcReg, DstRC);
-
- assert(canReplaceReg(DstReg, SrcReg, MRI) &&
- "Must be able to replace dst with src!");
- I.eraseFromParent();
- MRI.replaceRegWith(DstReg, SrcReg);
- return true;
- }
case TargetOpcode::G_EXTRACT: {
Register DstReg = I.getOperand(0).getReg();
Register SrcReg = I.getOperand(1).getReg();
>From 93d43c9f7fd5ded3f22428291335f31e720146c0 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Fri, 30 Jan 2026 13:43:35 +0000
Subject: [PATCH 6/6] address comments
---
.../CodeGen/AArch64/GlobalISel/166563.mir | 94 +++++++++----------
1 file changed, 44 insertions(+), 50 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
index 7e376f4f3c394..12e362e7b7fd2 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
@@ -5,12 +5,9 @@
---
name: pr166563
-alignment: 4
legalized: true
regBankSelected: true
tracksRegLiveness: true
-liveins:
- - { reg: '$w0', virtual-reg: '' }
body: |
; CHECK-LABEL: name: pr166563
; CHECK: bb.0:
@@ -67,48 +64,48 @@ body: |
successors: %bb.3(0x30000000), %bb.2(0x50000000)
liveins: $w0
- %2:gpr(s32) = COPY $w0
- %6:gpr(s64) = G_CONSTANT i64 457873110
- %36:gpr(s32) = G_CONSTANT i32 1
- G_BRCOND %36(s32), %bb.3
+ %0:gpr(s32) = COPY $w0
+ %1:gpr(s64) = G_CONSTANT i64 457873110
+ %2:gpr(s32) = G_CONSTANT i32 1
+ G_BRCOND %2(s32), %bb.3
G_BR %bb.2
bb.2:
successors: %bb.7(0x80000000)
- %7:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ %3:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
G_BR %bb.7
bb.3:
successors: %bb.4(0x40000000), %bb.5(0x40000000)
- %28:gpr(s32) = G_CONSTANT i32 1
- %29:gpr(s32) = G_XOR %2, %28
- %26:gpr(s32) = G_AND %29, %28
- G_BRCOND %26(s32), %bb.5
+ %4:gpr(s32) = G_CONSTANT i32 1
+ %5:gpr(s32) = G_XOR %0, %4
+ %6:gpr(s32) = G_AND %5, %4
+ G_BRCOND %6(s32), %bb.5
G_BR %bb.4
bb.4:
successors: %bb.6(0x80000000)
- %14:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
- %23:gpr(s64) = G_CONSTANT i64 -2
- %16:gpr(s64) = G_ADD %14, %23
+ %7:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
+ %8:gpr(s64) = G_CONSTANT i64 -2
+ %9:gpr(s64) = G_ADD %7, %8
G_BR %bb.6
bb.5:
- %12:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
- %24:gpr(s64) = G_CONSTANT i64 0
- %13:gpr(s64) = G_AND %24, %12
- $x0 = COPY %13(s64)
+ %10:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
+ %11:gpr(s64) = G_CONSTANT i64 0
+ %12:gpr(s64) = G_AND %11, %10
+ $x0 = COPY %12(s64)
RET_ReallyLR implicit $x0
bb.6:
successors: %bb.6(0x80000000)
- %17:gpr(s64) = G_PHI %16(s64), %bb.4, %19(s64), %bb.6
- %22:gpr(s64) = G_CONSTANT i64 -1
- %19:gpr(s64) = G_ADD %17, %22
+ %13:gpr(s64) = G_PHI %9(s64), %bb.4, %15(s64), %bb.6
+ %14:gpr(s64) = G_CONSTANT i64 -1
+ %15:gpr(s64) = G_ADD %13, %14
G_BR %bb.6
bb.7:
@@ -117,19 +114,16 @@ body: |
bb.8:
successors: %bb.8(0x7c000000), %bb.7(0x04000000)
- %25:gpr(s64) = G_CONSTANT i64 0
- %32:gpr(s32) = G_ICMP intpred(ugt), %7(s64), %25
- G_BRCOND %32(s32), %bb.8
+ %16:gpr(s64) = G_CONSTANT i64 0
+ %17:gpr(s32) = G_ICMP intpred(ugt), %3(s64), %16
+ G_BRCOND %17(s32), %bb.8
G_BR %bb.7
...
---
name: pr166563_commuted_and
-alignment: 4
legalized: true
regBankSelected: true
tracksRegLiveness: true
-liveins:
- - { reg: '$w0', virtual-reg: '' }
body: |
; CHECK-LABEL: name: pr166563_commuted_and
; CHECK: bb.0:
@@ -186,48 +180,48 @@ body: |
successors: %bb.3(0x30000000), %bb.2(0x50000000)
liveins: $w0
- %2:gpr(s32) = COPY $w0
- %6:gpr(s64) = G_CONSTANT i64 457873110
- %36:gpr(s32) = G_CONSTANT i32 1
- G_BRCOND %36(s32), %bb.3
+ %0:gpr(s32) = COPY $w0
+ %1:gpr(s64) = G_CONSTANT i64 457873110
+ %2:gpr(s32) = G_CONSTANT i32 1
+ G_BRCOND %2(s32), %bb.3
G_BR %bb.2
bb.2:
successors: %bb.7(0x80000000)
- %7:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
+ %3:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
G_BR %bb.7
bb.3:
successors: %bb.4(0x40000000), %bb.5(0x40000000)
- %28:gpr(s32) = G_CONSTANT i32 1
- %29:gpr(s32) = G_XOR %2, %28
- %26:gpr(s32) = G_AND %29, %28
- G_BRCOND %26(s32), %bb.5
+ %4:gpr(s32) = G_CONSTANT i32 1
+ %5:gpr(s32) = G_XOR %0, %4
+ %6:gpr(s32) = G_AND %5, %4
+ G_BRCOND %6(s32), %bb.5
G_BR %bb.4
bb.4:
successors: %bb.6(0x80000000)
- %14:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
- %23:gpr(s64) = G_CONSTANT i64 -2
- %16:gpr(s64) = G_ADD %14, %23
+ %7:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
+ %8:gpr(s64) = G_CONSTANT i64 -2
+ %9:gpr(s64) = G_ADD %7, %8
G_BR %bb.6
bb.5:
- %12:gpr(s64) = G_CONSTANT_FOLD_BARRIER %6
- %24:gpr(s64) = G_CONSTANT i64 0
- %13:gpr(s64) = G_AND %12, %24
- $x0 = COPY %13(s64)
+ %10:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
+ %11:gpr(s64) = G_CONSTANT i64 0
+ %12:gpr(s64) = G_AND %10, %11
+ $x0 = COPY %12(s64)
RET_ReallyLR implicit $x0
bb.6:
successors: %bb.6(0x80000000)
- %17:gpr(s64) = G_PHI %16(s64), %bb.4, %19(s64), %bb.6
- %22:gpr(s64) = G_CONSTANT i64 -1
- %19:gpr(s64) = G_ADD %17, %22
+ %13:gpr(s64) = G_PHI %9(s64), %bb.4, %15(s64), %bb.6
+ %14:gpr(s64) = G_CONSTANT i64 -1
+ %15:gpr(s64) = G_ADD %13, %14
G_BR %bb.6
bb.7:
@@ -236,8 +230,8 @@ body: |
bb.8:
successors: %bb.8(0x7c000000), %bb.7(0x04000000)
- %25:gpr(s64) = G_CONSTANT i64 0
- %32:gpr(s32) = G_ICMP intpred(ugt), %7(s64), %25
- G_BRCOND %32(s32), %bb.8
+ %16:gpr(s64) = G_CONSTANT i64 0
+ %17:gpr(s32) = G_ICMP intpred(ugt), %3(s64), %16
+ G_BRCOND %17(s32), %bb.8
G_BR %bb.7
...
More information about the llvm-commits
mailing list