[llvm] [Instcombine] Fix crash in foldMinimumMaximumSharedOp. (PR #173705)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 26 21:28:34 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Justin Lebar (jlebar)
<details>
<summary>Changes</summary>
We were missing a check that the inner intrinsic is in fact a min/max
op. We'd crash if it was any other intrinsic!
This was found by a fuzzer I'm working on. The high-level design is to
randomly generate LLVM IR, run a pass on it, and then run the original
and new IR through the interpreter. They should produce the same
results. Right now I'm only fuzzing instcombine.
---
Full diff: https://github.com/llvm/llvm-project/pull/173705.diff
2 Files Affected:
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+16-5)
- (added) llvm/test/Transforms/InstCombine/minmax-fp-shared-op.ll (+16)
``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 927d05b3f1eac..5ffa2a4143d08 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6554,10 +6554,21 @@ static Value *foldMinMaxSharedOp(Intrinsic::ID IID, Value *Op0, Value *Op1) {
/// is expected to swap the operand arguments to handle commutation.
static Value *foldMinimumMaximumSharedOp(Intrinsic::ID IID, Value *Op0,
Value *Op1) {
- assert((IID == Intrinsic::maxnum || IID == Intrinsic::minnum ||
- IID == Intrinsic::maximum || IID == Intrinsic::minimum ||
- IID == Intrinsic::maximumnum || IID == Intrinsic::minimumnum) &&
- "Unsupported intrinsic");
+ auto IsMinimumMaximumIntrinsic = [](Intrinsic::ID ID) {
+ switch (ID) {
+ case Intrinsic::maxnum:
+ case Intrinsic::minnum:
+ case Intrinsic::maximum:
+ case Intrinsic::minimum:
+ case Intrinsic::maximumnum:
+ case Intrinsic::minimumnum:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ assert(IsMinimumMaximumIntrinsic(IID) && "Unsupported intrinsic");
auto *M0 = dyn_cast<IntrinsicInst>(Op0);
// If Op0 is not the same intrinsic as IID, do not process.
@@ -6577,7 +6588,7 @@ static Value *foldMinimumMaximumSharedOp(Intrinsic::ID IID, Value *Op0,
return M0;
auto *M1 = dyn_cast<IntrinsicInst>(Op1);
- if (!M1)
+ if (!M1 || !IsMinimumMaximumIntrinsic(M1->getIntrinsicID()))
return nullptr;
Value *X1 = M1->getOperand(0);
Value *Y1 = M1->getOperand(1);
diff --git a/llvm/test/Transforms/InstCombine/minmax-fp-shared-op.ll b/llvm/test/Transforms/InstCombine/minmax-fp-shared-op.ll
new file mode 100644
index 0000000000000..856d2da523e35
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/minmax-fp-shared-op.ll
@@ -0,0 +1,16 @@
+; RUN: opt -passes=instcombine -S %s -o - | FileCheck %s
+
+declare float @llvm.minnum.f32(float, float)
+declare float @llvm.fma.f32(float, float, float)
+
+; CHECK-LABEL: @minnum_shared_op_mixed(
+; CHECK: call float @llvm.minnum.f32
+; CHECK: call float @llvm.fma.f32
+; CHECK: call float @llvm.minnum.f32
+define float @minnum_shared_op_mixed(float %x) {
+entry:
+ %m0 = call float @llvm.minnum.f32(float %x, float 0.000000e+00)
+ %f = call float @llvm.fma.f32(float %x, float 0.000000e+00, float %x)
+ %m2 = call float @llvm.minnum.f32(float %f, float %m0)
+ ret float %m2
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/173705
More information about the llvm-commits
mailing list