[llvm] [LoopInterchange] Support inner-loop simple reductions via UndoSimpleReduction (PR #172970)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 25 01:59:36 PST 2025
github-actions[bot] wrote:
<!--PREMERGE ADVISOR COMMENT: Windows-->
# :window: Windows x64 Test Results
* 128952 tests passed
* 2842 tests skipped
* 1 test failed
## Failed Tests
(click on a test name to see its output)
### LLVM
<details>
<summary>LLVM.Transforms/LoopInterchange/simple-reduction-limitation.ll</summary>
```
Exit Code: 2
Command Output (stdout):
--
# RUN: at line 2
c:\_work\llvm-project\llvm-project\build\bin\opt.exe < C:\_work\llvm-project\llvm-project\llvm\test\Transforms\LoopInterchange\simple-reduction-limitation.ll -passes="loop-interchange" -loop-interchange-undo-simple-reduction -pass-remarks-missed='loop-interchange' -pass-remarks-output=C:\_work\llvm-project\llvm-project\build\test\Transforms\LoopInterchange\Output\simple-reduction-limitation.ll.tmp -S | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe --input-file=C:\_work\llvm-project\llvm-project\build\test\Transforms\LoopInterchange\Output\simple-reduction-limitation.ll.tmp C:\_work\llvm-project\llvm-project\llvm\test\Transforms\LoopInterchange\simple-reduction-limitation.ll
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\opt.exe' -passes=loop-interchange -loop-interchange-undo-simple-reduction -pass-remarks-missed=loop-interchange '-pass-remarks-output=C:\_work\llvm-project\llvm-project\build\test\Transforms\LoopInterchange\Output\simple-reduction-limitation.ll.tmp' -S
# .---command stdout------------
# | ; ModuleID = '<stdin>'
# | source_filename = "<stdin>"
# |
# | define void @simple_reduction_01(ptr noalias readonly %a, ptr noalias readonly %b, ptr noalias writeonly %s, i64 %n) {
# | entry:
# | %cmp = icmp sgt i64 %n, 0
# | br i1 %cmp, label %outerloop_header.preheader, label %exit
# |
# | outerloop_header.preheader: ; preds = %entry
# | br label %outerloop_header
# |
# | outerloop_header: ; preds = %outerloop_header.preheader, %outerloop_latch
# | %index_i = phi i64 [ %index_i.next, %outerloop_latch ], [ 0, %outerloop_header.preheader ]
# | %addr_s = getelementptr inbounds nuw double, ptr %s, i64 %index_i
# | %invariant.gep.us = getelementptr inbounds nuw double, ptr %a, i64 %index_i
# | %invariant.gep32.us = getelementptr inbounds nuw double, ptr %b, i64 %index_i
# | %s_init = load double, ptr %addr_s, align 8
# | br label %innerloop
# |
# | innerloop: ; preds = %innerloop, %outerloop_header
# | %index_j = phi i64 [ 0, %outerloop_header ], [ %index_j.next, %innerloop ]
# | %reduction = phi double [ %s_init, %outerloop_header ], [ %add, %innerloop ]
# | %addr_a_j_i = getelementptr inbounds nuw double, ptr %invariant.gep.us, i64 %index_j
# | %0 = load double, ptr %addr_a_j_i, align 8
# | %addr_b_j_i = getelementptr inbounds nuw double, ptr %invariant.gep32.us, i64 %index_j
# | %1 = load double, ptr %addr_b_j_i, align 8
# | %mul = fmul fast double %1, %0
# | %add = fadd fast double %mul, %reduction
# | %index_j.next = add nuw nsw i64 %index_j, 1
# | %cond1 = icmp eq i64 %index_j.next, %n
# | br i1 %cond1, label %outerloop_latch, label %innerloop
# |
# | outerloop_latch: ; preds = %innerloop
# | %lcssa = phi double [ %add, %innerloop ]
# | store double %lcssa, ptr %addr_s, align 8
# | %index_i.next = add nuw nsw i64 %index_i, 1
# | %cond2 = icmp eq i64 %index_i.next, %n
# | br i1 %cond2, label %exit.loopexit, label %outerloop_header
# |
# | exit.loopexit: ; preds = %outerloop_latch
# | br label %exit
# |
# | exit: ; preds = %exit.loopexit, %entry
# | ret void
# | }
# |
# | define void @simple_reduction_02(ptr noalias readonly %a, ptr noalias readonly %b, ptr noalias writeonly %s, ptr noalias writeonly %s2, i64 %n) {
# | entry:
# | %cmp = icmp sgt i64 %n, 0
# | br i1 %cmp, label %outerloop_header.preheader, label %exit
# |
# | outerloop_header.preheader: ; preds = %entry
# | br label %outerloop_header
# |
# | outerloop_header: ; preds = %outerloop_header.preheader, %outerloop_latch
# | %index_i = phi i64 [ %index_i.next, %outerloop_latch ], [ 0, %outerloop_header.preheader ]
# | %addr_s = getelementptr inbounds nuw double, ptr %s, i64 %index_i
# | %addr_s2 = getelementptr inbounds nuw double, ptr %s2, i64 %index_i
# | %invariant.gep.us = getelementptr inbounds nuw double, ptr %a, i64 %index_i
# | %invariant.gep32.us = getelementptr inbounds nuw double, ptr %b, i64 %index_i
# | br label %innerloop
# |
# | innerloop: ; preds = %innerloop, %outerloop_header
# | %index_j = phi i64 [ 0, %outerloop_header ], [ %index_j.next, %innerloop ]
# | %reduction = phi double [ 0.000000e+00, %outerloop_header ], [ %add, %innerloop ]
# | %reduction2 = phi double [ 0.000000e+00, %outerloop_header ], [ %add2, %innerloop ]
# | %addr_a_j_i = getelementptr inbounds nuw double, ptr %invariant.gep.us, i64 %index_j
# | %0 = load double, ptr %addr_a_j_i, align 8
# | %addr_b_j_i = getelementptr inbounds nuw double, ptr %invariant.gep32.us, i64 %index_j
# | %1 = load double, ptr %addr_b_j_i, align 8
# | %mul = fmul fast double %1, %0
# | %add = fadd fast double %mul, %reduction
# | %add2 = fadd fast double %reduction2, %0
# | %index_j.next = add nuw nsw i64 %index_j, 1
# | %cond1 = icmp eq i64 %index_j.next, %n
# | br i1 %cond1, label %outerloop_latch, label %innerloop
# |
# | outerloop_latch: ; preds = %innerloop
# | %lcssa = phi double [ %add, %innerloop ]
# | %lcssa2 = phi double [ %add2, %innerloop ]
# | store double %lcssa, ptr %addr_s, align 8
# | store double %lcssa2, ptr %addr_s2, align 8
# | %index_i.next = add nuw nsw i64 %index_i, 1
# | %cond2 = icmp eq i64 %index_i.next, %n
# | br i1 %cond2, label %exit.loopexit, label %outerloop_header
# |
# | exit.loopexit: ; preds = %outerloop_latch
# | br label %exit
# |
# | exit: ; preds = %exit.loopexit, %entry
# | ret void
# | }
# |
# | define void @simple_reduction_03(ptr noalias readonly %a, ptr noalias readonly %b, ptr noalias writeonly %s, i64 %n) {
# | entry:
# | %cmp = icmp sgt i64 %n, 0
# | br i1 %cmp, label %outerloop_header.preheader, label %exit
# |
# | outerloop_header.preheader: ; preds = %entry
# | br label %outerloop_header
# |
# | outerloop_header: ; preds = %outerloop_header.preheader, %outerloop_latch
# | %index_i = phi i64 [ %index_i.next, %outerloop_latch ], [ 0, %outerloop_header.preheader ]
# | %addr_s = getelementptr inbounds nuw double, ptr %s, i64 %index_i
# | %invariant.gep.us = getelementptr inbounds nuw double, ptr %a, i64 %index_i
# | %invariant.gep32.us = getelementptr inbounds nuw double, ptr %b, i64 %index_i
# | br label %innerloop
# |
# | innerloop: ; preds = %innerloop, %outerloop_header
# | %index_j = phi i64 [ 0, %outerloop_header ], [ %index_j.next, %innerloop ]
# | %reduction = phi double [ 0.000000e+00, %outerloop_header ], [ %add, %innerloop ]
# | %addr_a_j_i = getelementptr inbounds nuw double, ptr %invariant.gep.us, i64 %index_j
# | %0 = load double, ptr %addr_a_j_i, align 8
# | %addr_b_j_i = getelementptr inbounds nuw double, ptr %invariant.gep32.us, i64 %index_j
# | %1 = load double, ptr %addr_b_j_i, align 8
# | %mul = fmul fast double %1, %0
# | %add = fadd fast double %mul, %reduction
# | %index_j.next = add nuw nsw i64 %index_j, 1
# | %cond1 = icmp eq i64 %index_j.next, %n
# | br i1 %cond1, label %outerloop_latch, label %innerloop
# |
# | outerloop_latch: ; preds = %innerloop
# | %lcssa = phi double [ %add, %innerloop ]
# | store double %lcssa, ptr %addr_s, align 8
# | %add17.us = fadd fast double %lcssa, 1.000000e+00
# | store double %add17.us, ptr %addr_s, align 8
# | %index_i.next = add nuw nsw i64 %index_i, 1
# | %cond2 = icmp eq i64 %index_i.next, %n
# | br i1 %cond2, label %exit.loopexit, label %outerloop_header
# |
# | exit.loopexit: ; preds = %outerloop_latch
# | br label %exit
# |
# | exit: ; preds = %exit.loopexit, %entry
# | ret void
# | }
# |
# | define void @simple_reduction_04(ptr noalias readonly %a, ptr noalias readonly %b, ptr noalias writeonly %c, ptr noalias writeonly %s, i64 %n) {
# | entry:
# | %cmp = icmp sgt i64 %n, 0
# | br i1 %cmp, label %i_loop_header.preheader, label %exit
# |
# | i_loop_header.preheader: ; preds = %entry
# | br label %i_loop_header
# |
# | i_loop_header: ; preds = %i_loop_header.preheader, %i_loop_latch
# | %index_i = phi i64 [ %index_i.next, %i_loop_latch ], [ 0, %i_loop_header.preheader ]
# | %addr_s = getelementptr inbounds nuw double, ptr %s, i64 %index_i
# | %invariant.gep.us = getelementptr inbounds nuw double, ptr %a, i64 %index_i
# | %invariant.gep32.us = getelementptr inbounds nuw double, ptr %b, i64 %index_i
# | br label %j_loop
# |
# | j_loop: ; preds = %j_loop_latch, %i_loop_header
# | %index_j = phi i64 [ 0, %i_loop_header ], [ %index_j.next, %j_loop_latch ]
# | %reduction = phi double [ 0.000000e+00, %i_loop_header ], [ %add, %j_loop_latch ]
# | %addr_a_j_i = getelementptr inbounds nuw double, ptr %invariant.gep.us, i64 %index_j
# | %0 = load double, ptr %addr_a_j_i, align 8
# | %addr_b_j_i = getelementptr inbounds nuw double, ptr %invariant.gep32.us, i64 %index_j
# | %1 = load double, ptr %addr_b_j_i, align 8
# | %mul = fmul fast double %1, %0
# | %add = fadd fast double %mul, %reduction
# | br label %k_loop
# |
# | k_loop: ; preds = %k_loop, %j_loop
# | %index_k = phi i64 [ %index_k.next, %k_loop ], [ 0, %j_loop ]
# | %arrayidx22.us.us = getelementptr inbounds nuw double, ptr %c, i64 %index_k
# | %index_k.next = add nuw nsw i64 %index_k, 1
# | %exitcond.not = icmp eq i64 %index_k.next, %n
# | br i1 %exitcond.not, label %j_loop_latch, label %k_loop
# |
# | j_loop_latch: ; preds = %k_loop
# | %index_j.next = add nuw nsw i64 %index_j, 1
# | %cond1 = icmp eq i64 %index_j.next, %n
# | br i1 %cond1, label %i_loop_latch, label %j_loop
# |
# | i_loop_latch: ; preds = %j_loop_latch
# | %lcssa = phi double [ %add, %j_loop_latch ]
# | store double %lcssa, ptr %addr_s, align 8
# | %index_i.next = add nuw nsw i64 %index_i, 1
# | %cond2 = icmp eq i64 %index_i.next, %n
# | br i1 %cond2, label %exit.loopexit, label %i_loop_header
# |
# | exit.loopexit: ; preds = %i_loop_latch
# | br label %exit
# |
# | exit: ; preds = %exit.loopexit, %entry
# | ret void
# | }
# |
# | define void @simple_reduction_05(ptr noalias readonly %a, ptr noalias readonly %b, ptr noalias writeonly %s, i64 %n) {
# | entry:
# | %cmp = icmp sgt i64 %n, 0
# | br i1 %cmp, label %outerloop_header.preheader, label %exit
# |
# | outerloop_header.preheader: ; preds = %entry
# | br label %outerloop_header
# |
# | outerloop_header: ; preds = %outerloop_header.preheader, %outerloop_latch
# | %index_i = phi i64 [ %index_i.next, %outerloop_latch ], [ 0, %outerloop_header.preheader ]
# | %invariant.gep.us = getelementptr inbounds nuw double, ptr %a, i64 %index_i
# | %invariant.gep32.us = getelementptr inbounds nuw double, ptr %b, i64 %index_i
# | br label %innerloop
# |
# | innerloop: ; preds = %innerloop, %outerloop_header
# | %index_j = phi i64 [ 0, %outerloop_header ], [ %index_j.next, %innerloop ]
# | %reduction = phi double [ 0.000000e+00, %outerloop_header ], [ %add, %innerloop ]
# | %addr_a_j_i = getelementptr inbounds nuw double, ptr %invariant.gep.us, i64 %index_j
# | %0 = load double, ptr %addr_a_j_i, align 8
# | %addr_b_j_i = getelementptr inbounds nuw double, ptr %invariant.gep32.us, i64 %index_j
# | %1 = load double, ptr %addr_b_j_i, align 8
# | %mul = fmul fast double %1, %0
# | %add = fadd fast double %mul, %reduction
# | %index_j.next = add nuw nsw i64 %index_j, 1
# | %cond1 = icmp eq i64 %index_j.next, %n
# | br i1 %cond1, label %outerloop_latch, label %innerloop
# |
# | outerloop_latch: ; preds = %innerloop
# | %lcssa = phi double [ %add, %innerloop ]
# | %addr_s = getelementptr inbounds nuw double, ptr %s, i64 %index_i
# | store double %lcssa, ptr %addr_s, align 8
# | %index_i.next = add nuw nsw i64 %index_i, 1
# | %cond2 = icmp eq i64 %index_i.next, %n
# | br i1 %cond2, label %exit.loopexit, label %outerloop_header
# |
# | exit.loopexit: ; preds = %outerloop_latch
# | br label %exit
# |
# | exit: ; preds = %exit.loopexit, %entry
# | ret void
# | }
# `-----------------------------
# .---command stderr------------
# | remark: <unknown>:0:0: Cannot undo a reduction with non-constant initial value.
# | remark: <unknown>:0:0: Only inner loops with induction or reduction PHI nodes can be interchange currently.
# | remark: <unknown>:0:0: Cannot undo a reduction with two or more reductions.
# | remark: <unknown>:0:0: Only inner loops with induction or reduction PHI nodes can be interchange currently.
# | remark: <unknown>:0:0: Cannot undo a reduction when the reduction is used more than once in the outer loop.
# | remark: <unknown>:0:0: Only inner loops with induction or reduction PHI nodes can be interchange currently.
# | remark: <unknown>:0:0: Only outer loops with induction or reduction PHI nodes can be interchanged currently.
# | remark: <unknown>:0:0: Cannot undo a reduction when the loop is not the innermost loop.
# | remark: <unknown>:0:0: Only inner loops with induction or reduction PHI nodes can be interchange currently.
# | remark: <unknown>:0:0: Cannot undo a reduction when memory reference does not dominate the inner loop.
# | remark: <unknown>:0:0: Only inner loops with induction or reduction PHI nodes can be interchange currently.
# `-----------------------------
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' '--input-file=C:\_work\llvm-project\llvm-project\build\test\Transforms\LoopInterchange\Output\simple-reduction-limitation.ll.tmp' 'C:\_work\llvm-project\llvm-project\llvm\test\Transforms\LoopInterchange\simple-reduction-limitation.ll'
# .---command stderr------------
# | Could not open input file 'C:\_work\llvm-project\llvm-project\build\test\Transforms\LoopInterchange\Output\simple-reduction-limitation.ll.tmp': no such file or directory
# `-----------------------------
# error: command failed with exit status: 2
--
```
</details>
If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label.
https://github.com/llvm/llvm-project/pull/172970
More information about the llvm-commits
mailing list