llvm-project/llvm/test/Transforms/PhaseOrdering/single-iteration-loop-sroa.ll
Roman Lebedev 8adfa29706
[Pipelines] Introduce SROA after (final, run-time) loop unrolling
Now that we are done with loop unrolling, be it either by LoopVectorizer,
or LoopUnroll passes, some variable-offset GEP's into alloca's could have
become constant-offset, thus enabling SROA and alloca promotion,
yet we don't capitalize on that, which is surprizing.

While it would be good to not introduce one more SROA invocation,
but instead move the one from `PassBuilder::buildFunctionSimplificationPipeline()`,
the existing test coverage says that is a bad idea,
though it would be fine compile-time wise: https://llvm-compile-time-tracker.com/compare.php?from=b150d34c47efbd8fa09604bce805c0920360f8d7&to=5a9a5c855158b482552be8c7af3e73d67fa44805&stat=instructions

So instead, i add yet another SROA run.
I have checked, and it needs to be at least after said final loop unrolling.
This is still fine compile-time wise: https://llvm-compile-time-tracker.com/compare.php?from=70324cd88328c0924e605fa81b696572560aa5c9&to=fb489bbef687ad821c3173a931709f9cad9aee8a&stat=instructions

I've encountered this in a real code, `SROA-after-final-loop-unrolling.ll` has been reduced from https://godbolt.org/z/fsdMhETh3

Reviewed By: spatel

Differential Revision: https://reviews.llvm.org/D136806
2022-11-17 21:31:30 +03:00

67 lines
3.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -O2 < %s | FileCheck %s
; Test a single-iteration loop that should get SROAd once we realize that fact.
; It should compile down to a bswap.
; The helper function exists to avoid IPSCCP breaking the loop too early.
define i16 @helper(i16 %0, i64 %x) {
; CHECK-LABEL: @helper(
; CHECK-NEXT: start:
; CHECK-NEXT: [[DATA:%.*]] = alloca [2 x i8], align 2
; CHECK-NEXT: store i16 [[TMP0:%.*]], ptr [[DATA]], align 2
; CHECK-NEXT: br label [[BB6_I_I:%.*]]
; CHECK: bb6.i.i:
; CHECK-NEXT: [[ITER_SROA_0_07_I_I:%.*]] = phi i64 [ [[TMP1:%.*]], [[BB6_I_I]] ], [ 0, [[START:%.*]] ]
; CHECK-NEXT: [[_40_I_I:%.*]] = sub nsw i64 0, [[ITER_SROA_0_07_I_I]]
; CHECK-NEXT: [[TMP1]] = add nuw nsw i64 [[ITER_SROA_0_07_I_I]], 1
; CHECK-NEXT: [[_34_I_I:%.*]] = getelementptr inbounds [0 x i8], ptr [[DATA]], i64 0, i64 [[ITER_SROA_0_07_I_I]]
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [0 x i8], ptr [[DATA]], i64 0, i64 [[_40_I_I]]
; CHECK-NEXT: [[_39_I_I:%.*]] = getelementptr i8, ptr [[TMP2]], i64 1
; CHECK-NEXT: [[TMP_0_COPYLOAD_I_I_I_I:%.*]] = load i8, ptr [[_34_I_I]], align 1
; CHECK-NEXT: [[TMP2_0_COPYLOAD_I_I_I_I:%.*]] = load i8, ptr [[_39_I_I]], align 1
; CHECK-NEXT: store i8 [[TMP2_0_COPYLOAD_I_I_I_I]], ptr [[_34_I_I]], align 1
; CHECK-NEXT: store i8 [[TMP_0_COPYLOAD_I_I_I_I]], ptr [[_39_I_I]], align 1
; CHECK-NEXT: [[EXITCOND_NOT_I_I:%.*]] = icmp eq i64 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND_NOT_I_I]], label [[EXIT:%.*]], label [[BB6_I_I]]
; CHECK: exit:
; CHECK-NEXT: [[DOTSROA_0_0_COPYLOAD:%.*]] = load i16, ptr [[DATA]], align 2
; CHECK-NEXT: ret i16 [[DOTSROA_0_0_COPYLOAD]]
;
start:
%data = alloca [2 x i8], align 2
store i16 %0, ptr %data, align 2
%1 = getelementptr inbounds i8, ptr %data, i64 2
%2 = getelementptr inbounds i8, ptr %1, i64 -1
br label %bb6.i.i
bb6.i.i:
%iter.sroa.0.07.i.i = phi i64 [ %4, %bb6.i.i ], [ 0, %start ]
%3 = xor i64 %iter.sroa.0.07.i.i, -1
%_40.i.i = add nsw i64 1, %3
%4 = add nuw nsw i64 %iter.sroa.0.07.i.i, 1
%_34.i.i = getelementptr inbounds [0 x i8], ptr %data, i64 0, i64 %iter.sroa.0.07.i.i
%_39.i.i = getelementptr inbounds [0 x i8], ptr %2, i64 0, i64 %_40.i.i
%tmp.0.copyload.i.i.i.i = load i8, ptr %_34.i.i, align 1
%tmp2.0.copyload.i.i.i.i = load i8, ptr %_39.i.i, align 1
store i8 %tmp2.0.copyload.i.i.i.i, ptr %_34.i.i, align 1
store i8 %tmp.0.copyload.i.i.i.i, ptr %_39.i.i, align 1
%exitcond.not.i.i = icmp eq i64 %4, %x
br i1 %exitcond.not.i.i, label %exit, label %bb6.i.i
exit:
%.sroa.0.0.copyload = load i16, ptr %data, align 2
ret i16 %.sroa.0.0.copyload
}
define i16 @test(i16 %arg) {
; CHECK-LABEL: @test(
; CHECK-NEXT: bb6.i.i.i:
; CHECK-NEXT: [[DATA_I_SROA_0_0_INSERT_INSERT:%.*]] = tail call i16 @llvm.bswap.i16(i16 [[ARG:%.*]])
; CHECK-NEXT: ret i16 [[DATA_I_SROA_0_0_INSERT_INSERT]]
;
%ret = call i16 @helper(i16 %arg, i64 1)
ret i16 %ret
}