Skip to content

[RISCV][VLOPT] Skip EMUL if it is unknown before entering EMULAndEEWAreEqual #139670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

BeMg
Copy link
Contributor

@BeMg BeMg commented May 13, 2025

Fix #139288

@llvmbot
Copy link
Member

llvmbot commented May 13, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Piyou Chen (BeMg)

Changes

Fix #139288


Full diff: https://github.com/llvm/llvm-project/pull/139670.diff

2 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp (+5)
  • (added) llvm/test/CodeGen/RISCV/rvv/139288-VLOPT-crash.ll (+22)
diff --git a/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp
index 9ed2ba274bc53..88876201ae21b 100644
--- a/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp
+++ b/llvm/lib/Target/RISCV/RISCVVLOptimizer.cpp
@@ -1383,6 +1383,11 @@ RISCVVLOptimizer::checkUsers(const MachineInstr &MI) const {
     // If the operand is used as a scalar operand, then the EEW must be
     // compatible. Otherwise, the EMUL *and* EEW must be compatible.
     bool IsVectorOpUsedAsScalarOp = isVectorOpUsedAsScalarOp(UserOp);
+
+    if (!IsVectorOpUsedAsScalarOp &&
+        (!ConsumerInfo->EMUL || !ProducerInfo->EMUL))
+      return std::nullopt;
+
     if ((IsVectorOpUsedAsScalarOp &&
          !OperandInfo::EEWAreEqual(*ConsumerInfo, *ProducerInfo)) ||
         (!IsVectorOpUsedAsScalarOp &&
diff --git a/llvm/test/CodeGen/RISCV/rvv/139288-VLOPT-crash.ll b/llvm/test/CodeGen/RISCV/rvv/139288-VLOPT-crash.ll
new file mode 100644
index 0000000000000..1e2f0173505c3
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/139288-VLOPT-crash.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv64 -mattr=+v < %s | FileCheck %s
+
+define i32 @pps_is_equal(<vscale x 16 x i1> %0, <vscale x 16 x i1> %1) #0 {
+; CHECK-LABEL: pps_is_equal:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetivli zero, 1, e32, m8, ta, ma
+; CHECK-NEXT:    vmclr.m v8
+; CHECK-NEXT:    vmv.s.x v16, zero
+; CHECK-NEXT:    vmor.mm v0, v8, v8
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vredmax.vs v8, v8, v16, v0.t
+; CHECK-NEXT:    vmv.x.s a0, v8
+; CHECK-NEXT:    ret
+entry:
+    %2 = tail call <vscale x 16 x i1> @llvm.vp.or.nxv16i1(<vscale x 16 x i1> zeroinitializer, <vscale x 16 x i1> zeroinitializer, <vscale x 16 x i1> %0, i32 1)
+    %3 = tail call i32 @llvm.vp.reduce.smax.nxv16i32(i32 0, <vscale x 16 x i32> zeroinitializer, <vscale x 16 x i1> %2, i32 1)
+    ret i32 %3
+}
+
+declare <vscale x 16 x i1> @llvm.vp.or.nxv16i1(<vscale x 16 x i1>, <vscale x 16 x i1>, <vscale x 16 x i1>, i32) #1
+declare i32 @llvm.vp.reduce.smax.nxv16i32(i32, <vscale x 16 x i32>, <vscale x 16 x i1>, i32) #1

Copy link
Contributor

@lukel97 lukel97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better if we just handle the nullopt EMUL case in EMULAndEEWAreEqual? Does it work if we just replace it with

  static bool EMULAndEEWAreEqual(const OperandInfo &A, const OperandInfo &B) {
    return A.Log2EEW == B.Log2EEW && A.EMUL == B.EMUL;
  }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, can you move this into vl-opt.ll and replace the VP intrinsics with RISC-V intrinsics? Just in case the VP intrinsics lowering ever changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I update the testcase inside the vl-opt.mir.

@BeMg
Copy link
Contributor Author

BeMg commented May 14, 2025

Would it be better if we just handle the nullopt EMUL case in EMULAndEEWAreEqual? Does it work if we just replace it with

  static bool EMULAndEEWAreEqual(const OperandInfo &A, const OperandInfo &B) {
    return A.Log2EEW == B.Log2EEW && A.EMUL == B.EMUL;
  }

Yes, It work.

@BeMg BeMg requested a review from lukel97 May 14, 2025 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RISCV] Assertion failure from std::optional in VLOptimizer
3 participants