[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