Skip to content

Commit 0195ec4

Browse files
authored
[flang] Add -f[no-]unroll-loops flag (llvm#122906)
1 parent 1797fb6 commit 0195ec4

File tree

8 files changed

+89
-3
lines changed

8 files changed

+89
-3
lines changed

clang/include/clang/Driver/Options.td

+2-2
Original file line numberDiff line numberDiff line change
@@ -4157,9 +4157,9 @@ def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group<f_Group>,
41574157
HelpText<"Issue call to specified function rather than a trap instruction">,
41584158
MarshallingInfoString<CodeGenOpts<"TrapFuncName">>;
41594159
def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>,
4160-
HelpText<"Turn on loop unroller">, Visibility<[ClangOption, CC1Option]>;
4160+
HelpText<"Turn on loop unroller">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>;
41614161
def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>,
4162-
HelpText<"Turn off loop unroller">, Visibility<[ClangOption, CC1Option]>;
4162+
HelpText<"Turn off loop unroller">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>;
41634163
def ffinite_loops: Flag<["-"], "ffinite-loops">, Group<f_Group>,
41644164
HelpText<"Assume all non-trivial loops are finite.">, Visibility<[ClangOption, CC1Option]>;
41654165
def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,

clang/lib/Driver/ToolChains/Flang.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ void Flang::addCodegenOptions(const ArgList &Args,
155155
options::OPT_flang_deprecated_no_hlfir,
156156
options::OPT_fno_ppc_native_vec_elem_order,
157157
options::OPT_fppc_native_vec_elem_order,
158-
options::OPT_ftime_report, options::OPT_ftime_report_EQ});
158+
options::OPT_ftime_report, options::OPT_ftime_report_EQ,
159+
options::OPT_funroll_loops, options::OPT_fno_unroll_loops});
159160
}
160161

161162
void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {

flang/include/flang/Frontend/CodeGenOptions.def

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the
3232
///< compile step.
3333
CODEGENOPT(StackArrays, 1, 0) ///< -fstack-arrays (enable the stack-arrays pass)
3434
CODEGENOPT(LoopVersioning, 1, 0) ///< Enable loop versioning.
35+
CODEGENOPT(UnrollLoops, 1, 0) ///< Enable loop unrolling
3536
CODEGENOPT(AliasAnalysis, 1, 0) ///< Enable alias analysis pass
3637

3738
CODEGENOPT(Underscoring, 1, 1)

flang/lib/Frontend/CompilerInvocation.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
246246
clang::driver::options::OPT_fno_loop_versioning, false))
247247
opts.LoopVersioning = 1;
248248

249+
opts.UnrollLoops = args.hasFlag(clang::driver::options::OPT_funroll_loops,
250+
clang::driver::options::OPT_fno_unroll_loops,
251+
(opts.OptimizationLevel > 1));
252+
249253
opts.AliasAnalysis = opts.OptimizationLevel > 0;
250254

251255
// -mframe-pointer=none/non-leaf/all option.

flang/lib/Frontend/FrontendActions.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,8 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
10281028
si.registerCallbacks(pic, &mam);
10291029
if (ci.isTimingEnabled())
10301030
si.getTimePasses().setOutStream(ci.getTimingStreamLLVM());
1031+
pto.LoopUnrolling = opts.UnrollLoops;
1032+
pto.LoopInterleaving = opts.UnrollLoops;
10311033
llvm::PassBuilder pb(targetMachine, pto, pgoOpt, &pic);
10321034

10331035
// Attempt to load pass plugins and register their callbacks with PB.

flang/test/Driver/funroll-loops.f90

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
! RUN: %flang -### -funroll-loops %s 2>&1 | FileCheck %s -check-prefix UNROLL
2+
! RUN: %flang -### -fno-unroll-loops %s 2>&1 | FileCheck %s -check-prefix NO-UNROLL
3+
4+
! UNROLL: "-funroll-loops"
5+
! NO-UNROLL: "-fno-unroll-loops"

flang/test/HLFIR/unroll-loops.fir

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %flang_fc1 -emit-llvm -O1 -funroll-loops -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,UNROLL
2+
// RUN: %flang_fc1 -emit-llvm -O2 -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,UNROLL
3+
// RUN: %flang_fc1 -emit-llvm -O1 -fno-unroll-loops -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,NO-UNROLL
4+
// RUN: %flang_fc1 -emit-llvm -O1 -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,NO-UNROLL
5+
6+
// CHECK-LABEL: @unroll
7+
// CHECK-SAME: (ptr nocapture writeonly %[[ARG0:.*]])
8+
func.func @unroll(%arg0: !fir.ref<!fir.array<1000 x index>> {fir.bindc_name = "a"}) {
9+
%scope = fir.dummy_scope : !fir.dscope
10+
%c1000 = arith.constant 1000 : index
11+
%shape = fir.shape %c1000 : (index) -> !fir.shape<1>
12+
%a:2 = hlfir.declare %arg0(%shape) dummy_scope %scope {uniq_name = "unrollEa"} : (!fir.ref<!fir.array<1000xindex>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<1000 x index>>, !fir.ref<!fir.array<1000 x index>>)
13+
%c1 = arith.constant 1 : index
14+
fir.do_loop %arg1 = %c1 to %c1000 step %c1 {
15+
// CHECK: br label %[[BLK:.*]]
16+
// CHECK: [[BLK]]:
17+
// CHECK-NEXT: %[[IND:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[NIV:.*]], %[[BLK]] ]
18+
// CHECK-NEXT: %[[VIND:.*]] = phi <2 x i64> [ <i64 1, i64 2>, %{{.*}} ], [ %[[NVIND:.*]], %[[BLK]] ]
19+
20+
// NO-UNROLL-NEXT: %[[GEP:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]]
21+
// NO-UNROLL-NEXT: store <2 x i64> %[[VIND]], ptr %[[GEP]]
22+
// NO-UNROLL-NEXT: %[[NIV:.*]] = add nuw i64 %{{.*}}, 2
23+
// NO-UNROLL-NEXT: %[[NVIND]] = add <2 x i64> %[[VIND]], splat (i64 2)
24+
25+
// UNROLL-NEXT: %[[VIND1:.*]] = add <2 x i64> %[[VIND]], splat (i64 2)
26+
// UNROLL-NEXT: %[[GEP0:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]]
27+
// UNROLL-NEXT: %[[GEP1:.*]] = getelementptr i8, ptr %[[GEP0]], i64 16
28+
// UNROLL-NEXT: store <2 x i64> %[[VIND]], ptr %[[GEP0]]
29+
// UNROLL-NEXT: store <2 x i64> %[[VIND1]], ptr %[[GEP1]]
30+
// UNROLL-NEXT: %[[NIV:.*]] = add nuw i64 %[[IND]], 4
31+
// UNROLL-NEXT: %[[NVIND:.*]] = add <2 x i64> %[[VIND]], splat (i64 4)
32+
33+
// CHECK-NEXT: %[[EXIT:.*]] = icmp eq i64 %[[NIV]], 1000
34+
// CHECK-NEXT: br i1 %[[EXIT]], label %{{.*}}, label %[[BLK]]
35+
%ai = hlfir.designate %a#0 (%arg1) : (!fir.ref<!fir.array<1000 x index>>, index) -> !fir.ref<index>
36+
hlfir.assign %arg1 to %ai : index, !fir.ref<index>
37+
}
38+
return
39+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
! RUN: %flang_fc1 -emit-llvm -O1 -funroll-loops -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,UNROLL
2+
! RUN: %flang_fc1 -emit-llvm -O2 -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,UNROLL
3+
! RUN: %flang_fc1 -emit-llvm -O1 -fno-unroll-loops -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,NO-UNROLL
4+
! RUN: %flang_fc1 -emit-llvm -O1 -mllvm -force-vector-width=2 -o- %s | FileCheck %s --check-prefixes=CHECK,NO-UNROLL
5+
6+
! CHECK-LABEL: @unroll
7+
! CHECK-SAME: (ptr nocapture writeonly %[[ARG0:.*]])
8+
subroutine unroll(a)
9+
integer(kind=8), intent(out) :: a(1000)
10+
integer(kind=8) :: i
11+
! CHECK: br label %[[BLK:.*]]
12+
! CHECK: [[BLK]]:
13+
! CHECK-NEXT: %[[IND:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[NIV:.*]], %[[BLK]] ]
14+
! CHECK-NEXT: %[[VIND:.*]] = phi <2 x i64> [ <i64 1, i64 2>, %{{.*}} ], [ %[[NVIND:.*]], %[[BLK]] ]
15+
!
16+
! NO-UNROLL-NEXT: %[[GEP:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]]
17+
! NO-UNROLL-NEXT: store <2 x i64> %[[VIND]], ptr %[[GEP]]
18+
! NO-UNROLL-NEXT: %[[NIV:.*]] = add nuw i64 %{{.*}}, 2
19+
! NO-UNROLL-NEXT: %[[NVIND]] = add <2 x i64> %[[VIND]], splat (i64 2)
20+
!
21+
! UNROLL-NEXT: %[[VIND1:.*]] = add <2 x i64> %[[VIND]], splat (i64 2)
22+
! UNROLL-NEXT: %[[GEP0:.*]] = getelementptr i64, ptr %[[ARG0]], i64 %[[IND]]
23+
! UNROLL-NEXT: %[[GEP1:.*]] = getelementptr i8, ptr %[[GEP0]], i64 16
24+
! UNROLL-NEXT: store <2 x i64> %[[VIND]], ptr %[[GEP0]]
25+
! UNROLL-NEXT: store <2 x i64> %[[VIND1]], ptr %[[GEP1]]
26+
! UNROLL-NEXT: %[[NIV:.*]] = add nuw i64 %[[IND]], 4
27+
! UNROLL-NEXT: %[[NVIND:.*]] = add <2 x i64> %[[VIND]], splat (i64 4)
28+
!
29+
! CHECK-NEXT: %[[EXIT:.*]] = icmp eq i64 %[[NIV]], 1000
30+
! CHECK-NEXT: br i1 %[[EXIT]], label %{{.*}}, label %[[BLK]]
31+
do i=1,1000
32+
a(i) = i
33+
end do
34+
end subroutine

0 commit comments

Comments
 (0)