aboutsummaryrefslogtreecommitdiff
path: root/llvm
diff options
context:
space:
mode:
authorCullen Rhodes <cullen.rhodes@arm.com>2026-02-02 10:04:12 +0000
committerGitHub <noreply@github.com>2026-02-02 10:04:12 +0000
commitf288f463ad0e7bb9c48198a2bbc2f8b979b986cf (patch)
tree6b7d746db260983a37cf170ce957dd83ea63d5b7 /llvm
parent2f3935bcee6eaf7df8c85a21b7c0fbef967316b5 (diff)
downloadllvm-main.zip
llvm-main.tar.gz
llvm-main.tar.bz2
[AArch64][GlobalISel] Constrain G_CONSTANT_FOLD_BARRIER operand register classes (#177997)HEADmain
[AArch64][GlobalISel] Constrain G_CONSTANT_FOLD_BARRIER operand 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 the reason for this is there are multiple G_CONSTANT_FOLD_BARRIER ops with the same input register: Select: %14:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr Erasing: %14:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64sp -- Select: %12:gpr64(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64sp Erasing: %12:gpr64(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64 -- Select: %7:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64 Erasing: %7:gpr64sp(s64) = G and the middle one used by the AND gets overridden by last and becomes invalid. this patch fixes this by constraining the register class such that the middle one gets constrained to the subset of gpr64sp and gpr64, i.e. gpr64common: Select: %14:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr Erasing: %14:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64sp -- Select: %12:gpr64(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64sp Erasing: %12:gpr64(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64common -- Select: %7:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64common Erasing: %7:gpr64sp(s64) = G_CONSTANT_FOLD_BARRIER %6:gpr64common canReplaceReg doesnt handle when both regs already have classes so the assert is removed. Fixes #166563.
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp7
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/166563.mir237
2 files changed, 241 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index fc379b5..5fb31a0 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -366,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/test/CodeGen/AArch64/GlobalISel/166563.mir b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
new file mode 100644
index 0000000..12e362e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/166563.mir
@@ -0,0 +1,237 @@
+# 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
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+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]+]]: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
+ ; 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: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[COPY1]], [[SUBREG_TO_REG]]
+ ; 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
+
+ %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)
+
+ %3:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
+ G_BR %bb.7
+
+ bb.3:
+ successors: %bb.4(0x40000000), %bb.5(0x40000000)
+
+ %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)
+
+ %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:
+ %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)
+
+ %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:
+ successors: %bb.8(0x80000000)
+
+ bb.8:
+ successors: %bb.8(0x7c000000), %bb.7(0x04000000)
+
+ %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
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+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]+]]: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
+ ; 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: [[ANDXrr:%[0-9]+]]:gpr64 = ANDXrr [[SUBREG_TO_REG]], [[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
+
+ %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)
+
+ %3:gpr(s64) = G_CONSTANT_FOLD_BARRIER %1
+ G_BR %bb.7
+
+ bb.3:
+ successors: %bb.4(0x40000000), %bb.5(0x40000000)
+
+ %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)
+
+ %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:
+ %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)
+
+ %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:
+ successors: %bb.8(0x80000000)
+
+ bb.8:
+ successors: %bb.8(0x7c000000), %bb.7(0x04000000)
+
+ %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
+...