[llvm] [LLVM][InstCombine] Add simplification of SVE compare intrinsics. (PR #211249)

Matthew Devereau via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 29 03:38:42 PDT 2026


================
@@ -1964,6 +2018,72 @@ simplifySVEIntrinsicBinOp(InstCombiner &IC, IntrinsicInst &II,
   return IC.replaceInstUsesWith(II, SimpleII);
 }
 
+static std::optional<Instruction *>
+simplifySVEIntrinsicCompare(InstCombiner &IC, IntrinsicInst &II,
+                            const SVEIntrinsicInfo &IInfo) {
+  const unsigned Opc = IInfo.getMatchingIROpode();
+  assert((Opc == Instruction::ICmp || Opc == Instruction::FCmp) &&
+         "Expected a compare operation!");
+
+  Value *Pg = II.getOperand(0);
+  Value *LHS = II.getOperand(1);
+  Value *RHS = II.getOperand(2);
+  CmpInst::Predicate CmpPred = IInfo.getCmpPredicate();
+  bool IsWideICmp =
+      Opc == Instruction::ICmp && LHS->getType() != RHS->getType();
+  assert((IsWideICmp || LHS->getType() == RHS->getType()) &&
+         "Unexpected wide compare!");
+
+  // Canonicalise constants to the RHS.
+  if ((ICmpInst::isCommutative(CmpPred) || FCmpInst::isCommutative(CmpPred)) &&
+      isa<Constant>(LHS) && !isa<Constant>(RHS) && !IsWideICmp) {
+    IC.replaceOperand(II, 1, RHS);
+    IC.replaceOperand(II, 2, LHS);
+    return &II;
+  }
+
+  // Only active lanes matter when simplifying the operation.
+  LHS = stripInactiveLanes(LHS, Pg);
+  RHS = stripInactiveLanes(RHS, Pg);
+
+  if (IsWideICmp) {
+    // We can do more for wide compares, but not using simplifyCmpInst.
+    const APInt *LHSVal, *RHSVal;
+    if (!match(LHS, m_APInt(LHSVal)) || !match(RHS, m_APInt(RHSVal)))
+      return std::nullopt;
+
+    // Consider cmpge.wide(..., <vscale x 4 x i32> LHS, <vscale x 2 x i64> RHS),
+    // we must reconstruct the constants because LHS has the wrong element type,
+    // and RHS the wrong element count.
+    Type *WideVT = VectorType::get(RHS->getType()->getScalarType(),
+                                   cast<VectorType>(LHS->getType()));
+    if (ICmpInst::isSigned(CmpPred)) {
----------------
MDevereau wrote:

This check is only inclusive of SGT, SGE, SLT and SLE so it looks incorrect for cmpeq/cmpne:

```define <vscale x 4 x i1> @constant_icmpeq_wide_negative(<vscale x 4 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 4 x i1> @constant_icmpeq_wide_negative(
; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    ret <vscale x 4 x i1> zeroinitializer
;
  %r = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpeq.wide.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat (i32 -1), <vscale x 2 x i64> splat (i64 -1))
  ret <vscale x 4 x i1> %r
}
```


```
define <vscale x 4 x i1> @constant_icmpne_wide_negative(<vscale x 4 x i1> %pg) #0 {
; CHECK-LABEL: define <vscale x 4 x i1> @constant_icmpne_wide_negative(
; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    ret <vscale x 4 x i1> [[PG]]
;
  %r = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpne.wide.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat (i32 -1), <vscale x 2 x i64> splat (i64 -1))
  ret <vscale x 4 x i1> %r
}
```

https://github.com/llvm/llvm-project/pull/211249


More information about the llvm-commits mailing list