[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