[llvm] r369886 - [LoopUnroll] Handle certain PHIs in full unrolling properly

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 28 02:53:45 PDT 2019


Merged to release_90 in r370182.

On Mon, Aug 26, 2019 at 11:28 AM Bjorn Pettersson via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: bjope
> Date: Mon Aug 26 02:29:53 2019
> New Revision: 369886
>
> URL: http://llvm.org/viewvc/llvm-project?rev=369886&view=rev
> Log:
> [LoopUnroll] Handle certain PHIs in full unrolling properly
>
> Summary:
> When reconstructing the CFG of the loop after unrolling,
> LoopUnroll could in some cases remove the phi operands of
> loop-carried values instead of preserving them, resulting
> in undef phi values after loop unrolling.
>
> When doing this reconstruction, avoid removing incoming
> phi values for phis in the successor blocks if the successor
> is the block we are jumping to anyway.
>
> Patch-by: ebevhan
>
> Reviewers: fhahn, efriedma
>
> Reviewed By: fhahn
>
> Subscribers: bjope, lebedev.ri, zzheng, dmgreen, llvm-commits
>
> Tags: #llvm
>
> Differential Revision: https://reviews.llvm.org/D66334
>
> Added:
>     llvm/trunk/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll
> Modified:
>     llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
>
> Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=369886&r1=369885&r2=369886&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Mon Aug 26 02:29:53 2019
> @@ -711,7 +711,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *
>
>    auto setDest = [LoopExit, ContinueOnTrue](BasicBlock *Src, BasicBlock *Dest,
>                                              ArrayRef<BasicBlock *> NextBlocks,
> -                                            BasicBlock *CurrentHeader,
> +                                            BasicBlock *BlockInLoop,
>                                              bool NeedConditional) {
>      auto *Term = cast<BranchInst>(Src->getTerminator());
>      if (NeedConditional) {
> @@ -723,7 +723,9 @@ LoopUnrollResult llvm::UnrollLoop(Loop *
>        if (Dest != LoopExit) {
>          BasicBlock *BB = Src;
>          for (BasicBlock *Succ : successors(BB)) {
> -          if (Succ == CurrentHeader)
> +          // Preserve the incoming value from BB if we are jumping to the block
> +          // in the current loop.
> +          if (Succ == BlockInLoop)
>              continue;
>            for (PHINode &Phi : Succ->phis())
>              Phi.removeIncomingValue(BB, false);
> @@ -794,7 +796,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *
>          // unconditional branch for some iterations.
>          NeedConditional = false;
>
> -      setDest(Headers[i], Dest, Headers, Headers[i], NeedConditional);
> +      setDest(Headers[i], Dest, Headers, HeaderSucc[i], NeedConditional);
>      }
>
>      // Set up latches to branch to the new header in the unrolled iterations or
>
> Added: llvm/trunk/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll?rev=369886&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll (added)
> +++ llvm/trunk/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll Mon Aug 26 02:29:53 2019
> @@ -0,0 +1,107 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt < %s -S -loop-unroll -unroll-allow-partial | FileCheck %s
> +
> +; The phi which acts as input to func should not be undef. It should
> +; have its loop-carried value (the load in for.cond) replaced accordingly
> +; after unrolling the loop.
> +
> +define i16 @full_unroll(i16* %A) {
> +; CHECK-LABEL: @full_unroll(
> +; CHECK-NEXT:  entry:
> +; CHECK-NEXT:    br label [[FOR_COND:%.*]]
> +; CHECK:       for.cond:
> +; CHECK-NEXT:    [[TMP2:%.*]] = load i16, i16* [[A:%.*]]
> +; CHECK-NEXT:    br label [[FOR_COND_CLEANUP3:%.*]]
> +; CHECK:       for.cond.cleanup:
> +; CHECK-NEXT:    [[DOTLCSSA10_LCSSA:%.*]] = phi i16 [ [[TMP2_2:%.*]], [[FOR_COND_CLEANUP3_2:%.*]] ]
> +; CHECK-NEXT:    [[TMP3:%.*]] = call i16 @func(i16 [[DOTLCSSA10_LCSSA]])
> +; CHECK-NEXT:    ret i16 0
> +; CHECK:       for.cond.cleanup3:
> +; CHECK-NEXT:    [[PTR_1:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 1
> +; CHECK-NEXT:    [[TMP2_1:%.*]] = load i16, i16* [[PTR_1]]
> +; CHECK-NEXT:    br label [[FOR_COND_CLEANUP3_1:%.*]]
> +; CHECK:       for.cond.cleanup3.1:
> +; CHECK-NEXT:    [[PTR_2:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 2
> +; CHECK-NEXT:    [[TMP2_2]] = load i16, i16* [[PTR_2]]
> +; CHECK-NEXT:    br label [[FOR_COND_CLEANUP3_2]]
> +; CHECK:       for.cond.cleanup3.2:
> +; CHECK-NEXT:    [[PTR_3:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 3
> +; CHECK-NEXT:    [[TMP2_3:%.*]] = load i16, i16* [[PTR_3]]
> +; CHECK-NEXT:    br i1 false, label [[FOR_COND_CLEANUP3_3:%.*]], label [[FOR_COND_CLEANUP:%.*]]
> +; CHECK:       for.cond.cleanup3.3:
> +; CHECK-NEXT:    unreachable
> +;
> +entry:
> +  br label %for.cond
> +
> +for.cond:                                         ; preds = %for.cond.cleanup3, %entry
> +  %.lcssa10 = phi i16 [ 123, %entry ], [ %.lcssa, %for.cond.cleanup3 ]
> +  %i.0 = phi i64 [ 0, %entry ], [ %inc9, %for.cond.cleanup3 ]
> +  %ptr = getelementptr inbounds i16, i16* %A, i64 %i.0
> +  %tmp2 = load i16, i16* %ptr
> +  %cmp = icmp ult i64 %i.0, 3
> +  br i1 %cmp, label %for.cond.cleanup3, label %for.cond.cleanup
> +
> +for.cond.cleanup:                                 ; preds = %for.cond
> +  %.lcssa10.lcssa = phi i16 [ %.lcssa10, %for.cond ]
> +  %tmp3 = call i16 (i16) @func(i16 %.lcssa10.lcssa)
> +  ret i16 0
> +
> +for.cond.cleanup3:                                ; preds = %for.cond
> +  %.lcssa = phi i16 [ %tmp2, %for.cond ]
> +  %inc9 = add i64 %i.0, 1
> +  br label %for.cond
> +}
> +
> +define i16 @partial_unroll(i16* %A) {
> +; CHECK-LABEL: @partial_unroll(
> +; CHECK-NEXT:  entry:
> +; CHECK-NEXT:    br label [[FOR_COND:%.*]]
> +; CHECK:       for.cond:
> +; CHECK-NEXT:    [[I_0:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC9_2:%.*]], [[FOR_COND_CLEANUP3_2:%.*]] ]
> +; CHECK-NEXT:    [[PTR:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i64 [[I_0]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = load i16, i16* [[PTR]]
> +; CHECK-NEXT:    br label [[FOR_COND_CLEANUP3:%.*]]
> +; CHECK:       for.cond.cleanup:
> +; CHECK-NEXT:    [[DOTLCSSA10_LCSSA:%.*]] = phi i16 [ [[TMP2_1:%.*]], [[FOR_COND_CLEANUP3_1:%.*]] ]
> +; CHECK-NEXT:    [[TMP3:%.*]] = call i16 @func(i16 [[DOTLCSSA10_LCSSA]])
> +; CHECK-NEXT:    ret i16 0
> +; CHECK:       for.cond.cleanup3:
> +; CHECK-NEXT:    [[INC9:%.*]] = add nuw nsw i64 [[I_0]], 1
> +; CHECK-NEXT:    [[PTR_1:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 [[INC9]]
> +; CHECK-NEXT:    [[TMP2_1]] = load i16, i16* [[PTR_1]]
> +; CHECK-NEXT:    br label [[FOR_COND_CLEANUP3_1]]
> +; CHECK:       for.cond.cleanup3.1:
> +; CHECK-NEXT:    [[INC9_1:%.*]] = add nuw nsw i64 [[INC9]], 1
> +; CHECK-NEXT:    [[PTR_2:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 [[INC9_1]]
> +; CHECK-NEXT:    [[TMP2_2:%.*]] = load i16, i16* [[PTR_2]]
> +; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult i64 [[INC9_1]], 200
> +; CHECK-NEXT:    br i1 [[CMP_2]], label [[FOR_COND_CLEANUP3_2]], label [[FOR_COND_CLEANUP:%.*]]
> +; CHECK:       for.cond.cleanup3.2:
> +; CHECK-NEXT:    [[INC9_2]] = add nuw nsw i64 [[INC9_1]], 1
> +; CHECK-NEXT:    br label [[FOR_COND]]
> +;
> +entry:
> +  br label %for.cond
> +
> +for.cond:                                         ; preds = %for.cond.cleanup3, %entry
> +  %.lcssa10 = phi i16 [ 123, %entry ], [ %.lcssa, %for.cond.cleanup3 ]
> +  %i.0 = phi i64 [ 0, %entry ], [ %inc9, %for.cond.cleanup3 ]
> +  %ptr = getelementptr inbounds i16, i16* %A, i64 %i.0
> +  %tmp2 = load i16, i16* %ptr
> +  %cmp = icmp ult i64 %i.0, 200
> +  br i1 %cmp, label %for.cond.cleanup3, label %for.cond.cleanup
> +
> +for.cond.cleanup:                                 ; preds = %for.cond
> +  %.lcssa10.lcssa = phi i16 [ %.lcssa10, %for.cond ]
> +  %tmp3 = call i16 (i16) @func(i16 %.lcssa10.lcssa)
> +  ret i16 0
> +
> +for.cond.cleanup3:                                ; preds = %for.cond
> +  %.lcssa = phi i16 [ %tmp2, %for.cond ]
> +  %inc9 = add i64 %i.0, 1
> +  br label %for.cond
> +}
> +
> +declare i16 @func(i16)
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list