Skip to content

Commit 51d3bc6

Browse files
authored
[flang][tco] Add more flags for generating codegen tests (#148171)
Built on top of #146533 Adding some more options I use to generate minimal testcases for MLIR->LLVMIR conversion. Hopefully this will save us all some time when writing these tests. The following options are added - `-simplify-mlir` runs CSE and canonicalization at the end of the MLIR pipeline - `-enable-aa` allows toggling whether TBAA is enabled - `-test-gen` is shorthand for `-emit-final-mlir -simplify-mlir -enable-aa=false`
1 parent ffb2da2 commit 51d3bc6

File tree

2 files changed

+130
-3
lines changed

2 files changed

+130
-3
lines changed

flang/test/Driver/tco-test-gen.fir

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// RUN: tco -emit-final-mlir %s | FileCheck %s --check-prefixes=CHECK,AA,CMPLX
2+
// RUN: tco -emit-final-mlir -enable-aa=false %s | FileCheck %s --check-prefixes=CHECK,NOAA,CMPLX
3+
// RUN: tco -emit-final-mlir -simplify-mlir %s | FileCheck %s --check-prefixes=CHECK,AA,SIMPLE
4+
// RUN: tco -emit-final-mlir -enable-aa=false -simplify-mlir %s | FileCheck %s --check-prefixes=CHECK,NOAA,SIMPLE
5+
// RUN: tco -test-gen %s | FileCheck %s --check-prefixes=CHECK,NOAA,SIMPLE
6+
7+
// Just a dummy function that exhibits all of the things we want to turn on and off
8+
func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.ref<i32> {fir.bindc_name = "lb"}, %arg2: !fir.ref<i32> {fir.bindc_name = "ub"}, %arg3: !fir.ref<i32> {fir.bindc_name = "step"}) {
9+
%0 = fir.dummy_scope : !fir.dscope
10+
%1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtestEi"}
11+
%2:2 = hlfir.declare %1 {uniq_name = "_QFtestEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
12+
%3:2 = hlfir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtestElb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
13+
%4:2 = hlfir.declare %arg0 dummy_scope %0 {uniq_name = "_QFtestEnum"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
14+
%5:2 = hlfir.declare %arg3 dummy_scope %0 {uniq_name = "_QFtestEstep"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
15+
%6:2 = hlfir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtestEub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
16+
%7 = fir.load %3#0 : !fir.ref<i32>
17+
%8 = fir.convert %7 : (i32) -> index
18+
%9 = fir.load %6#0 : !fir.ref<i32>
19+
%10 = fir.convert %9 : (i32) -> index
20+
%11 = fir.load %5#0 : !fir.ref<i32>
21+
%12 = fir.convert %11 : (i32) -> index
22+
%13 = fir.convert %8 : (index) -> i32
23+
%14:2 = fir.do_loop %arg4 = %8 to %10 step %12 iter_args(%arg5 = %13) -> (index, i32) {
24+
fir.store %arg5 to %2#0 : !fir.ref<i32>
25+
%15 = fir.load %4#0 : !fir.ref<i32>
26+
%16 = fir.load %2#0 : !fir.ref<i32>
27+
%17 = arith.addi %15, %16 : i32
28+
hlfir.assign %17 to %4#0 : i32, !fir.ref<i32>
29+
%18 = arith.addi %arg4, %12 overflow<nsw> : index
30+
%19 = fir.convert %12 : (index) -> i32
31+
%20 = fir.load %2#0 : !fir.ref<i32>
32+
%21 = arith.addi %20, %19 overflow<nsw> : i32
33+
fir.result %18, %21 : index, i32
34+
}
35+
fir.store %14#1 to %2#0 : !fir.ref<i32>
36+
return
37+
}
38+
39+
// CHECK-LABEL: llvm.func @_QPtest(
40+
// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr {fir.bindc_name = "num", llvm.nocapture},
41+
// CHECK-SAME: %[[ARG1:.*]]: !llvm.ptr {fir.bindc_name = "lb", llvm.nocapture},
42+
// CHECK-SAME: %[[ARG2:.*]]: !llvm.ptr {fir.bindc_name = "ub", llvm.nocapture},
43+
// CHECK-SAME: %[[ARG3:.*]]: !llvm.ptr {fir.bindc_name = "step", llvm.nocapture}) {
44+
45+
// CMPLX: %[[VAL_0:.*]] = llvm.mlir.constant(1 : i64) : i64
46+
// CMPLX: %[[VAL_1:.*]] = llvm.alloca %[[VAL_0]] x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
47+
// CMPLX: %[[VAL_2:.*]] = llvm.mlir.constant(1 : index) : i64
48+
// CMPLX: %[[VAL_3:.*]] = llvm.mlir.constant(0 : index) : i64
49+
// CMPLX: %[[VAL_4:.*]] = llvm.mlir.constant(1 : i64) : i64
50+
51+
// SIMPLE: %[[VAL_3:.*]] = llvm.mlir.constant(0 : index) : i64
52+
// SIMPLE: %[[VAL_2:.*]] = llvm.mlir.constant(1 : index) : i64
53+
// SIMPLE: %[[VAL_0:.*]] = llvm.mlir.constant(1 : i64) : i64
54+
// SIMPLE: %[[VAL_1:.*]] = llvm.alloca %[[VAL_0]] x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
55+
56+
// AA: %[[VAL_5:.*]] = llvm.load %[[ARG1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestElb", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestElb", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
57+
// NOAA: %[[VAL_5:.*]] = llvm.load %[[ARG1]] : !llvm.ptr -> i32
58+
59+
// CHECK: %[[VAL_6:.*]] = llvm.sext %[[VAL_5]] : i32 to i64
60+
61+
// AA: %[[VAL_7:.*]] = llvm.load %[[ARG2]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestEub", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestEub", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
62+
// NOAA: %[[VAL_7:.*]] = llvm.load %[[ARG2]] : !llvm.ptr -> i32
63+
64+
// CHECK: %[[VAL_8:.*]] = llvm.sext %[[VAL_7]] : i32 to i64
65+
66+
// AA: %[[VAL_9:.*]] = llvm.load %[[ARG3]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestEstep", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestEstep", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
67+
// NOAA: %[[VAL_9:.*]] = llvm.load %[[ARG3]] : !llvm.ptr -> i32
68+
69+
// CHECK: %[[VAL_10:.*]] = llvm.sext %[[VAL_9]] : i32 to i64
70+
// CHECK: %[[VAL_11:.*]] = llvm.trunc %[[VAL_6]] : i64 to i32
71+
// CHECK: %[[VAL_12:.*]] = llvm.sub %[[VAL_8]], %[[VAL_6]] : i64
72+
// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_10]] : i64
73+
// CHECK: %[[VAL_14:.*]] = llvm.sdiv %[[VAL_13]], %[[VAL_10]] : i64
74+
// CHECK: llvm.br ^bb1(%[[VAL_11]], %[[VAL_14]] : i32, i64)
75+
// CHECK: ^bb1(%[[VAL_15:.*]]: i32, %[[VAL_16:.*]]: i64):
76+
// CHECK: %[[VAL_17:.*]] = llvm.icmp "sgt" %[[VAL_16]], %{{.*}} : i64
77+
// CHECK: llvm.cond_br %[[VAL_17]], ^bb2, ^bb3
78+
// CHECK: ^bb2:
79+
80+
// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
81+
// NOAA: llvm.store %[[VAL_15]], %{{.*}} : i32, !llvm.ptr
82+
83+
// AA: %[[VAL_18:.*]] = llvm.load %[[ARG0]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
84+
// NOAA: %[[VAL_18:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
85+
86+
// AA: %[[VAL_19:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
87+
// NOAA: %[[VAL_19:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32
88+
89+
// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_18]], %[[VAL_19]] : i32
90+
// AA: llvm.store %[[VAL_20]], %[[ARG0]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
91+
// NOAA: llvm.store %[[VAL_20]], %[[ARG0]] : i32, !llvm.ptr
92+
93+
// CHECK: %[[VAL_21:.*]] = llvm.trunc %[[VAL_10]] : i64 to i32
94+
95+
// AA: %[[VAL_22:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
96+
// NOAA: %[[VAL_22:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32
97+
98+
// CHECK: %[[VAL_23:.*]] = llvm.add %[[VAL_22]], %[[VAL_21]] overflow<nsw> : i32
99+
// CHECK: %[[VAL_24:.*]] = llvm.sub %[[VAL_16]], %{{.*}} : i64
100+
// CHECK: llvm.br ^bb1(%[[VAL_23]], %[[VAL_24]] : i32, i64)
101+
// CHECK: ^bb3:
102+
103+
// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
104+
// NOAA: llvm.store %[[VAL_15]], %{{.*}} : i32, !llvm.ptr
105+
106+
// CHECK: llvm.return
107+
// CHECK: }
108+

flang/tools/tco/tco.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ static cl::opt<bool> emitFinalMLIR(
7575
cl::desc("Only translate FIR to MLIR, do not lower to LLVM IR"),
7676
cl::init(false));
7777

78+
static cl::opt<bool>
79+
simplifyMLIR("simplify-mlir",
80+
cl::desc("Run CSE and canonicalization on MLIR output"),
81+
cl::init(false));
82+
83+
// Enabled by default to accurately reflect -O2
84+
static cl::opt<bool> enableAliasAnalysis("enable-aa",
85+
cl::desc("Enable FIR alias analysis"),
86+
cl::init(true));
87+
88+
static cl::opt<bool> testGeneratorMode(
89+
"test-gen", cl::desc("-emit-final-mlir -simplify-mlir -enable-aa=false"),
90+
cl::init(false));
91+
7892
#include "flang/Optimizer/Passes/CommandLineOpts.h"
7993
#include "flang/Optimizer/Passes/Pipelines.h"
8094

@@ -145,7 +159,7 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
145159
} else {
146160
MLIRToLLVMPassPipelineConfig config(llvm::OptimizationLevel::O2);
147161
config.EnableOpenMP = true; // assume the input contains OpenMP
148-
config.AliasAnalysis = true; // enabled when optimizing for speed
162+
config.AliasAnalysis = enableAliasAnalysis && !testGeneratorMode;
149163
if (codeGenLLVM) {
150164
// Run only CodeGen passes.
151165
fir::createDefaultFIRCodeGenPassPipeline(pm, config);
@@ -154,14 +168,19 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) {
154168
fir::registerDefaultInlinerPass(config);
155169
fir::createMLIRToLLVMPassPipeline(pm, config);
156170
}
157-
if (!emitFinalMLIR)
171+
if (simplifyMLIR || testGeneratorMode) {
172+
pm.addPass(mlir::createCanonicalizerPass());
173+
pm.addPass(mlir::createCSEPass());
174+
}
175+
if (!emitFinalMLIR && !testGeneratorMode)
158176
fir::addLLVMDialectToLLVMPass(pm, out.os());
159177
}
160178

161179
// run the pass manager
162180
if (mlir::succeeded(pm.run(*owningRef))) {
163181
// passes ran successfully, so keep the output
164-
if ((emitFir || passPipeline.hasAnyOccurrences() || emitFinalMLIR) &&
182+
if ((emitFir || passPipeline.hasAnyOccurrences() || emitFinalMLIR ||
183+
testGeneratorMode) &&
165184
!codeGenLLVM)
166185
printModule(*owningRef, out.os());
167186
out.keep();

0 commit comments

Comments
 (0)