[llvm] [ValueTracking] Fold max/min when incrementing/decrementing by 1 (PR #142466)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 3 23:23:59 PDT 2025


================
@@ -564,6 +564,57 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal,
   return nullptr;
 }
 
+/// Try to fold a select to a min/max intrinsic. Many cases are already handled
+/// by matchDecomposedSelectPattern but here we handle the cases where more
+/// exensive modification of the IR is required.
+static Value *foldSelectICmpMinMax(const ICmpInst *Cmp, Value *TVal,
+                                   Value *FVal,
+                                   InstCombiner::BuilderTy &Builder,
+                                   const SimplifyQuery &SQ) {
+  const Value *CmpLHS = Cmp->getOperand(0);
+  const Value *CmpRHS = Cmp->getOperand(1);
+  ICmpInst::Predicate Pred = Cmp->getPredicate();
+
+  // (X > Y) ? X : (Y - 1) ==> MIN(X, Y - 1)
+  // (X < Y) ? X : (Y + 1) ==> MAX(X, Y + 1)
+  // This transformation is valid when overflow corresponding to the sign of
+  // the comparison is poison and we must drop the non-matching overflow flag.
+  if (CmpRHS == TVal) {
+    std::swap(CmpLHS, CmpRHS);
+    Pred = CmpInst::getSwappedPredicate(Pred);
+  }
+
+  if (CmpLHS == TVal) {
+    if (Pred == CmpInst::ICMP_SGT &&
+        match(FVal, m_NSWAddLike(m_Specific(CmpRHS), m_One()))) {
+      cast<Instruction>(FVal)->setHasNoUnsignedWrap(false);
----------------
dtcxzyw wrote:

`FVal` may be an `or disjoint` instruction.
Crash reproducer:
```
; bin/opt -passes=instcombine test.ll -S
define <2 x i16> @test_smax_add1_nsw_vec1(<2 x i16> %x, <2 x i16> %w) {
  %cmp = icmp sgt <2 x i16> %x, %w
  %add1 = or disjoint <2 x i16> %w, splat (i16 1)
  %r = select <2 x i1> %cmp, <2 x i16> %x, <2 x i16> %add1
  ret <2 x i16> %r
}
```
```
opt: /home/dtcxzyw/WorkSpace/Projects/compilers/llvm-project/llvm/include/llvm/Support/Casting.h:578: decltype(auto) llvm::cast(From*) [with To = TruncInst; From = Instruction]: Assertion `isa<To>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/opt -passes=instcombine src.ll -S
1.      Running pass "function(instcombine<max-iterations=1;verify-fixpoint>)" on module "src.ll"
2.      Running pass "instcombine<max-iterations=1;verify-fixpoint>" on function "test_smax_add1_nsw_vec1"
 #0 0x000074450a0279f2 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.21.0git+0x2279f2)
 #1 0x000074450a0248cf llvm::sys::RunSignalHandlers() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMSupport.so.21.0git+0x2248cf)
 #2 0x000074450a024a14 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x0000744509a45330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
 #4 0x0000744509a9eb2c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x0000744509a9eb2c __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x0000744509a9eb2c pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x0000744509a4527e raise ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x0000744509a288ff abort ./stdlib/abort.c:81:7
 #9 0x0000744509a2881b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x0000744509a3b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#11 0x0000744500685d26 llvm::Instruction::setHasNoUnsignedWrap(bool) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.21.0git+0x285d26)
#12 0x00007445019617e0 foldSelectICmpMinMax(llvm::ICmpInst const*, llvm::Value*, llvm::Value*, llvm::IRBuilder<llvm::TargetFolder, llvm::IRBuilderCallbackInserter>&, llvm::SimplifyQuery const&) InstCombineSelect.cpp:0:0
#13 0x000074450196c5be llvm::InstCombinerImpl::foldSelectInstWithICmp(llvm::SelectInst&, llvm::ICmpInst*) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.21.0git+0x1655be)
#14 0x0000744501970dcb llvm::InstCombinerImpl::visitSelectInst(llvm::SelectInst&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.21.0git+0x169dcb)
#15 0x000074450186e8f8 llvm::InstCombinerImpl::run() (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.21.0git+0x678f8)
#16 0x000074450186fa03 combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) InstructionCombining.cpp:0:0
#17 0x0000744501870a12 llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMInstCombine.so.21.0git+0x69a12)
#18 0x0000744503dac4e5 llvm::detail::PassModel<llvm::Function, llvm::InstCombinePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libPolly.so.21.0git+0x1ac4e5)
#19 0x00007445007271a4 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.21.0git+0x3271a4)
#20 0x0000744508cdb835 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.21.0git+0xdb835)
#21 0x00007445007276c0 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.21.0git+0x3276c0)
#22 0x0000744508cdc1f5 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMX86CodeGen.so.21.0git+0xdc1f5)
#23 0x0000744500728845 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/../lib/libLLVMCore.so.21.0git+0x328845)
#24 0x000074450a2aa3d9 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.21.0git+0x2d3d9)
#25 0x000074450a2b5416 optMain (/home/dtcxzyw/WorkSpace/Projects/compilers/LLVM/llvm-build/bin/../lib/libLLVMOptDriver.so.21.0git+0x38416)
#26 0x0000744509a2a1ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#27 0x0000744509a2a28b call_init ./csu/../csu/libc-start.c:128:20
#28 0x0000744509a2a28b __libc_start_main ./csu/../csu/libc-start.c:347:5
#29 0x00005b0447f99095 _start (bin/opt+0x1095)

Aborted (core dumped)
```

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


More information about the llvm-commits mailing list