[llvm] [LSR] Narrow search space by merging users outside and inside loop (PR #202676)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 13:01:16 PDT 2026


nikic wrote:

AI generated test case:
```llvm
; Probe for #202676: NarrowSearchSpaceByMergingUsesOutsideLoop widens the
; merged-into use's [MinOffset, MaxOffset] via pushFixup but, unlike
; NarrowSearchSpaceByCollapsingUnrolledCode, never deletes formulae of the
; merged-into use that are no longer legal for the widened offset range.
; Expected failure mode (assertions build): "Illegal formula generated!"
; assert after Solve() in LSRInstance::LSRInstance.
;
; RUN: opt -mtriple=x86_64 -loop-reduce -S < %s
;
; Stream 0 has two in-loop loads at relative offsets {-2^30, 0}, which makes
; GenerateConstantOffsets produce formulae with BaseOffset +2^30. The exit
; block loads at +1.5*2^30 past the post-inc pointer; x86 accepts that as a
; disp32, so the merge gate isLegalUse(LU.MinOffset, LU.MaxOffset, ...,
; Formulae[0]) passes, but 2^30 + 1.5*2^30 = 2.5*2^30 does not fit in a
; signed 32-bit displacement, so the +2^30 formulae become illegal once the
; outside-loop fixup is merged in. The test is sized so that the merge itself
; drops EstimateSearchSpaceComplexity() below ComplexityLimit, so no later
; narrowing step deletes the now-illegal formulae before Solve().

define i32 @illegal_formula_after_merge(ptr %p, i64 %n) {
entry:
  %p0.load = load ptr, ptr %p, align 8
  %arrayidx1 = getelementptr ptr, ptr %p, i64 1
  %p1.load = load ptr, ptr %arrayidx1, align 8
  %arrayidx2 = getelementptr ptr, ptr %p, i64 2
  %p2.load = load ptr, ptr %arrayidx2, align 8
  %arrayidx3 = getelementptr ptr, ptr %p, i64 3
  %p3.load = load ptr, ptr %arrayidx3, align 8
  br label %for.body

for.body:
  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]
  %off = phi i64 [ %off.next, %for.body ], [ 32, %entry ]
  %ret.0 = phi i32 [ %ret.2b, %for.body ], [ 0, %entry ]
  %p0 = getelementptr i32, ptr %p0.load, i64 %off
  %val0 = load i32, ptr %p0, align 4
  %ret.1 = add nsw i32 %val0, %ret.0
  %p0.low = getelementptr i8, ptr %p0, i64 -1073741824
  %val0b = load i32, ptr %p0.low, align 4
  %ret.1b = add nsw i32 %val0b, %ret.1
  %p1 = getelementptr i32, ptr %p1.load, i64 %off
  %val1 = load i32, ptr %p1, align 4
  %ret.2 = add nsw i32 %val1, %ret.1b
  %p2 = getelementptr i32, ptr %p2.load, i64 %off
  %val2 = load i32, ptr %p2, align 4
  %ret.2a = add nsw i32 %val2, %ret.2
  %p3 = getelementptr i32, ptr %p3.load, i64 %off
  %val3 = load i32, ptr %p3, align 4
  %ret.2c = add nsw i32 %val3, %ret.2a
  %iv.next = add nuw nsw i64 %iv, 1
  %off.next = add nuw nsw i64 %off, 1
  %exitcond = icmp eq i64 %iv.next, %n
  %ret.2b = add nsw i32 %ret.2c, 1
  br i1 %exitcond, label %exit, label %for.body

exit:
  %p0.last = getelementptr i32, ptr %p0.load, i64 %off.next
  %p0.far = getelementptr i8, ptr %p0.last, i64 1610612736
  %valfar = load i32, ptr %p0.far, align 4
  %ret.3 = add nsw i32 %ret.2b, %valfar
  ret i32 %ret.3
}
```

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


More information about the llvm-commits mailing list