[llvm] [IndVarSimplify] Relax Restrictions on Loop Counter Stride (PR #146992)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 7 00:06:34 PDT 2025


buggfg wrote:

@nikic Thanks so much for your attention!

* Four LIT test cases failure

  From what I've observed, The four test cases causing build failures on Windows and Linux are already failing in the LLVM main branch. 

* Masking issue

  First, I reproduced the masking issue and did some analysis on a test case. Here’s what I observed:

  By relaxing the stride restriction, the decrementing IV(in line 11) is recognized as a LoopCounter, allowing LFTR to further simplify the loop termination condition. However, this optimization exposes an existing issue in LLVM's design. As shown in line 11, the IV's type is promoted to i64 by the '`AllowIVWidening`' in `IndVarSimplifyPass`, while the second operand in the `icmp` (the constant `0`) remains of type i32. This type mismatch leads to the generation of a `trunc` instruction on line 14 that truncates the IV to i32 type. **This trunc is unnecessary** because the comparison could be performed using the original i64 type without any loss of information.

  ```
  1   ; *** Befor IndVarSimplifyPass  ***
  2   6:                                                
  3      %.0.in10 = phi i32 [ %3, %.lr.ph ], [ %.0, %6 ]
  4      %.0 = add nsw i32 %.0.in10, -1
  5      ...
  6      %17 = icmp sgt i32 %.0.in10, 1
  7      br i1 %17, label %6, label %._crit_edge.loopexit, !llvm.loop !33
  8  
  9   ; *** After IndVarSimplifyPass  ***
  10  7:      
  11    %indvars.iv = phi i64 [ %6, %.lr.ph ], [ %indvars.iv.next, %7 ]
  12    %indvars.iv.next = add nsw i64 %indvars.iv, -1
  13    ...
  14    %lftr.wideiv = trunc i64 %indvars.iv.next to i32
  15    %exitcond = icmp ne i32 %lftr.wideiv, 0
  16    br i1 %exitcond, label %7, label %._crit_edge.loopexit, !llvm.loop !33
  ```

  As a result, the `InstCombinePass` optimizes the trunc instruction into a masking instruction, leading to the masking issue.	

  ```
  1  ; *** After InstCombinePass***
  2  7:
  3    ...
  4    %17 = and i64 %indvars.iv.next, 4294967295
  5    %exitcond.not = icmp eq i64 %17, 0
  6    br i1 %exitcond.not, label %._crit_edge.loopexit, label %7, !llvm.loop !41
  ```

In summary, the masking issue is caused by the unnecessary trunc operation. Do you think I should add further checks for trunc in IndVarSimplify, or should I address the masking issue in InstCombine? :)

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


More information about the llvm-commits mailing list