[llvm] bbaa04b - [GlobalISel][AArch64] Tweak `G_FREEZE` legalization, don't push it when that makes code illegal (#204785)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 29 01:02:06 PDT 2026
Author: Ömer Sinan Ağacan
Date: 2026-06-29T09:02:01+01:00
New Revision: bbaa04b4ba4c9a6049e0618e97d7d1db85a8a06c
URL: https://github.com/llvm/llvm-project/commit/bbaa04b4ba4c9a6049e0618e97d7d1db85a8a06c
DIFF: https://github.com/llvm/llvm-project/commit/bbaa04b4ba4c9a6049e0618e97d7d1db85a8a06c.diff
LOG: [GlobalISel][AArch64] Tweak `G_FREEZE` legalization, don't push it when that makes code illegal (#204785)
In the combine rule
// Convert freeze(Op(Op0, NonPoisonOps...)) to Op(freeze(Op0), NonPoisonOps...)
// when Op0 is not guaranteed non-poison
def push_freeze_to_prevent_poison_from_propagating ...
Don't push the `freeze` if `freeze(Op0)` is illegal and we've already
run the legalizer.
Also make `G_FREEZE`, `G_IMPLICIT_DEF`, `G_CONSTANT_FOLD_BARRIER` legal for
`s128` operands.
Two new tests added:
- `free-push-legal.mir` checks that we don't push `freeze` towards operands
post-legalization when doing so makes the code illegal.
We use an instruction here that's unlikely to be made legal for `G_FREEZE`
(variable sized vector load).
- `freeze-push-legal.mir` checks the opposite on `s128` values.
Fixes the crashes like:
LLVM ERROR: instruction is not legal: %8:_(i128) = G_FREEZE %0:_ (in function: _0)
Added:
llvm/test/CodeGen/AArch64/GlobalISel/freeze-push.mir
Modified:
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index b4809c95f872c..ab0003cab6c2a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -252,6 +252,8 @@ void CombinerHelper::applyCombineCopy(MachineInstr &MI) const {
bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
MachineInstr &MI, BuildFnTy &MatchInfo) const {
+ assert(MI.getOpcode() == TargetOpcode::G_FREEZE && "Invalid instruction");
+
// Ported from InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating.
Register DstOp = MI.getOperand(0).getReg();
Register OrigOp = MI.getOperand(1).getReg();
@@ -306,6 +308,10 @@ bool CombinerHelper::matchFreezeOfSingleMaybePoisonOperand(
Register MaybePoisonOperandReg = MaybePoisonOperand->getReg();
LLT MaybePoisonOperandRegTy = MRI.getType(MaybePoisonOperandReg);
+ if (!isLegalOrBeforeLegalizer(
+ {TargetOpcode::G_FREEZE, {MaybePoisonOperandRegTy}}))
+ return false;
+
MatchInfo = [=](MachineIRBuilder &B) mutable {
Observer.changingInstr(*OrigDef);
cast<GenericMachineInstr>(OrigDef)->dropPoisonGeneratingFlags();
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index e6521a211226e..6eb8d87082055 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -133,7 +133,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
getActionDefinitionsBuilder(
{G_IMPLICIT_DEF, G_FREEZE, G_CONSTANT_FOLD_BARRIER})
- .legalFor({p0, s8, s16, s32, s64})
+ .legalFor({p0, s8, s16, s32, s64, s128})
.legalFor({v2s8, v4s8, v8s8, v16s8, v2s16, v4s16, v8s16, v2s32, v4s32,
v2s64, v2p0})
.widenScalarToNextPow2(0)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/freeze-push.mir b/llvm/test/CodeGen/AArch64/GlobalISel/freeze-push.mir
new file mode 100644
index 0000000000000..37db93b881730
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/freeze-push.mir
@@ -0,0 +1,50 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=arm64-apple-macosx -run-pass=aarch64-postlegalizer-combiner %s -o - | FileCheck %s
+---
+name: freeze_push_legal
+legalized: true
+body: |
+ bb.0.entry:
+ liveins: $x0
+ ; CHECK-LABEL: name: freeze_push_legal
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(i128) = G_LOAD [[COPY]](p0) :: (load (i128))
+ ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(i128) = G_FREEZE [[LOAD]]
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i64) = G_TRUNC [[FREEZE]](i128)
+ ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(i32) = G_TRUNC [[TRUNC]](i64)
+ ; CHECK-NEXT: $w0 = COPY [[TRUNC1]](i32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(p0) = COPY $x0
+ %1:_(i128) = G_LOAD %0(p0) :: (load (i128))
+ %4:_(i64), %5:_(i64) = G_UNMERGE_VALUES %1(i128)
+ %6:_(i64) = G_FREEZE %4
+ %3:_(i32) = G_TRUNC %6(i64)
+ $w0 = COPY %3(i32)
+ RET_ReallyLR implicit $w0
+...
+---
+name: freeze_push_illegal
+legalized: true
+body: |
+ bb.0.entry:
+ liveins: $x0
+ ; CHECK-LABEL: name: freeze_push_illegal
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s32>))
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[EVEC:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[LOAD]](<vscale x 4 x s32>), [[C]](s64)
+ ; CHECK-NEXT: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[EVEC]]
+ ; CHECK-NEXT: $w0 = COPY [[FREEZE]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(p0) = COPY $x0
+ %1:_(<vscale x 4 x s32>) = G_LOAD %0(p0) :: (load (<vscale x 4 x s32>))
+ %2:_(s64) = G_CONSTANT i64 0
+ %3:_(s32) = G_EXTRACT_VECTOR_ELT %1, %2
+ %4:_(s32) = G_FREEZE %3
+ $w0 = COPY %4(s32)
+ RET_ReallyLR implicit $w0
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir
index 9726cc59ed06f..72196862cfbd4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-undef.mir
@@ -9,8 +9,8 @@ body: |
; CHECK-LABEL: name: test_implicit_def
; CHECK: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
; CHECK-NEXT: $x0 = COPY [[DEF]](s64)
- %0:_(s128) = G_IMPLICIT_DEF
- %1:_(s64) = G_TRUNC %0(s128)
+ %0:_(s256) = G_IMPLICIT_DEF
+ %1:_(s64) = G_TRUNC %0(s256)
$x0 = COPY %1(s64)
...
@@ -104,6 +104,6 @@ body: |
; CHECK-LABEL: name: test_implicit_def_s88
; CHECK: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
; CHECK-NEXT: $x0 = COPY [[DEF]](s64)
- %undef:_(s88) = G_IMPLICIT_DEF
+ %undef:_(s130) = G_IMPLICIT_DEF
%trunc:_(s64) = G_TRUNC %undef
$x0 = COPY %trunc(s64)
More information about the llvm-commits
mailing list