[llvm] b7a20c1 - [GlobalISel] Don't permit G_*MIN/G_*MAX of pointer vectors (#168872)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 17 01:03:46 PST 2025
Author: Nathan Corbyn
Date: 2025-12-17T09:03:41Z
New Revision: b7a20c1cc4eae8b265ad28586d16439acc35678d
URL: https://github.com/llvm/llvm-project/commit/b7a20c1cc4eae8b265ad28586d16439acc35678d
DIFF: https://github.com/llvm/llvm-project/commit/b7a20c1cc4eae8b265ad28586d16439acc35678d.diff
LOG: [GlobalISel] Don't permit G_*MIN/G_*MAX of pointer vectors (#168872)
- Use `LLT::changeElementType()` instead of `LLT::changeElementSize()`
in `LegalizerHelper::lowerMinMax()` to avoid a crash in the case that
the destination type is a pointer vector;
- Reject `G_*MIN`/`G_*MAX` of pointers and pointer vectors in
`MachineVerifier`;
- Don't combine `G_SELECT`+`G_ICMP` pairs into `G_*MIN`/`G_*MAX` generic
instructions when the operands are pointers / pointer vectors.
Fixes #166556
Added:
llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll
llvm/test/MachineVerifier/test_g_minmax.mir
Modified:
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
llvm/lib/CodeGen/MachineVerifier.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index f0fbe0135353f..c58969144dc2b 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7556,7 +7556,7 @@ bool CombinerHelper::matchSelectIMinMax(const MachineOperand &MO,
Register False = Select->getFalseReg();
LLT DstTy = MRI.getType(DstReg);
- if (DstTy.isPointer())
+ if (DstTy.isPointerOrPointerVector())
return false;
// We want to fold the icmp and replace the select.
@@ -8511,4 +8511,4 @@ bool CombinerHelper::matchSuboCarryOut(const MachineInstr &MI,
}
return false;
-}
\ No newline at end of file
+}
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 802738ba19a70..6fce22e091cf9 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -8663,7 +8663,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
auto [Dst, Src0, Src1] = MI.getFirst3Regs();
const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
- LLT CmpType = MRI.getType(Dst).changeElementSize(1);
+ LLT CmpType = MRI.getType(Dst).changeElementType(LLT::scalar(1));
auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 9be741d96e456..5ce7606b051a5 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2276,6 +2276,16 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
report("addr operand must be a pointer", &AddrOp, 1);
break;
}
+ case TargetOpcode::G_SMIN:
+ case TargetOpcode::G_SMAX:
+ case TargetOpcode::G_UMIN:
+ case TargetOpcode::G_UMAX: {
+ const LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
+ if (DstTy.isPointerOrPointerVector())
+ report("Generic smin/smax/umin/umax does not support pointer operands",
+ MI);
+ break;
+ }
default:
break;
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll b/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll
new file mode 100644
index 0000000000000..4405c06ff0e23
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -global-isel -stop-after=legalizer -o - %s | FileCheck %s
+target triple = "aarch64"
+
+; Check we don't crash here or try to generate an ill-formed `G_UMAX` of
+; pointer vectors.
+
+define <4 x ptr> @pr168872(<4 x ptr> %ptrs) {
+ ; CHECK-LABEL: name: pr168872
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $q0, $q1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[C]](p0), [[C]](p0)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<2 x s64>) = G_ICMP intpred(ugt), [[BITCAST]](<2 x p0>), [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(<2 x s64>) = G_ICMP intpred(ugt), [[BITCAST1]](<2 x p0>), [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST2]](<2 x p0>)
+ ; CHECK-NEXT: [[PTRTOINT1:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST3]](<2 x p0>)
+ ; CHECK-NEXT: [[PTRTOINT2:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BUILD_VECTOR]](<2 x p0>)
+ ; CHECK-NEXT: [[PTRTOINT3:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BUILD_VECTOR]](<2 x p0>)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
+ ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C1]](s64), [[C1]](s64)
+ ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[ICMP]], [[BUILD_VECTOR1]]
+ ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(<2 x s64>) = G_XOR [[ICMP1]], [[BUILD_VECTOR1]]
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<2 x s64>) = G_AND [[PTRTOINT]], [[ICMP]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(<2 x s64>) = G_AND [[PTRTOINT1]], [[ICMP1]]
+ ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(<2 x s64>) = G_AND [[PTRTOINT2]], [[XOR]]
+ ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(<2 x s64>) = G_AND [[PTRTOINT3]], [[XOR1]]
+ ; CHECK-NEXT: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[AND]], [[AND2]]
+ ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(<2 x s64>) = G_OR [[AND1]], [[AND3]]
+ ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(<2 x p0>) = G_INTTOPTR [[OR]](<2 x s64>)
+ ; CHECK-NEXT: [[INTTOPTR1:%[0-9]+]]:_(<2 x p0>) = G_INTTOPTR [[OR1]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR]](<2 x p0>)
+ ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR1]](<2 x p0>)
+ ; CHECK-NEXT: $q0 = COPY [[BITCAST4]](<2 x s64>)
+ ; CHECK-NEXT: $q1 = COPY [[BITCAST5]](<2 x s64>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0, implicit $q1
+entry:
+ %cmp = icmp ugt <4 x ptr> %ptrs, zeroinitializer
+ %ptrs.select = select <4 x i1> %cmp, <4 x ptr> %ptrs, <4 x ptr> zeroinitializer
+ ret <4 x ptr> %ptrs.select
+}
diff --git a/llvm/test/MachineVerifier/test_g_minmax.mir b/llvm/test/MachineVerifier/test_g_minmax.mir
new file mode 100644
index 0000000000000..f05c1939778ff
--- /dev/null
+++ b/llvm/test/MachineVerifier/test_g_minmax.mir
@@ -0,0 +1,29 @@
+# RUN: not --crash llc -mtriple=arm64 -global-isel -run-pass=none -filetype=null %s 2>&1 | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+---
+name: test_minmax
+body: |
+ bb.0:
+ ; Pointer operands
+ %0:_(p0) = G_CONSTANT i64 0
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %1:_(p0) = G_SMIN %0, %0
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %2:_(p0) = G_SMAX %0, %0
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %2:_(p0) = G_UMIN %0, %0
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %4:_(p0) = G_UMAX %0, %0
+
+ ; Pointer vector operands
+ %5:_(<4 x p0>) = G_IMPLICIT_DEF
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %6:_(<4 x p0>) = G_SMIN %5, %5
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %6:_(<4 x p0>) = G_SMIN %5, %5
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %6:_(<4 x p0>) = G_SMIN %5, %5
+ ; CHECK: Bad machine code: Generic smin/smax/umin/umax does not support pointer operands
+ %6:_(<4 x p0>) = G_SMIN %5, %5
+...
More information about the llvm-commits
mailing list