Skip to content

Commit 8be4641

Browse files
[flang] Use hlfir.cmpchar for SELECT CASE of charsSelect case hlfir cmpchar (#168476)
For SELECT CASE with character selector, instead of allways calling runtime comparison function, emit hlfir.cmpchar. This has different behaviors at different optimization levels: at -O0, it still emits flang-rt call, but at higher optimization levels it does inline comparison. Modify test/Lower/select-case-statement.f90 to test both comparison cases.
1 parent 9d2b7ec commit 8be4641

File tree

2 files changed

+96
-56
lines changed

2 files changed

+96
-56
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3926,14 +3926,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
39263926
if (!isCharSelector)
39273927
return mlir::arith::CmpIOp::create(*builder, loc, pred, selector,
39283928
rhs);
3929-
fir::factory::CharacterExprHelper charHelper{*builder, loc};
3930-
std::pair<mlir::Value, mlir::Value> lhsVal =
3931-
charHelper.createUnboxChar(selector);
3932-
std::pair<mlir::Value, mlir::Value> rhsVal =
3933-
charHelper.createUnboxChar(rhs);
3934-
return fir::runtime::genCharCompare(*builder, loc, pred, lhsVal.first,
3935-
lhsVal.second, rhsVal.first,
3936-
rhsVal.second);
3929+
else
3930+
return hlfir::CmpCharOp::create(*builder, loc, pred, selector, rhs);
39373931
};
39383932
mlir::Block *newBlock = insertBlock(*caseBlock);
39393933
if (mlir::isa<fir::ClosedIntervalAttr>(attr)) {

flang/test/Lower/select-case-statement.f90

Lines changed: 94 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -119,31 +119,55 @@ subroutine scharacter(c)
119119
select case (c)
120120
case default
121121
nn = -1
122-
! CHECK: CharacterCompareScalar1
123-
! CHECK-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
122+
! NOTE: common pattern of character comparison: at -O0, runtime function
123+
! is called, followed by comparison of i32 values. At -O1 and above,
124+
! inline comparison code is done using loops. The comparison code ends
125+
! with comparison of i8 values. At either -O0 or -O1, the comparison
126+
! ends with a conditional branch. This comparison pattern is used
127+
! throughout this file.
128+
!
129+
! <= 'd'
130+
! CHECK-O0: CharacterCompareScalar1
131+
! CHECK-O0-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
132+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
133+
! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
124134
! CHECK-NEXT: cf.cond_br
125135
case (:'d')
126136
nn = 10
127-
! CHECK: CharacterCompareScalar1
128-
! CHECK-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
137+
! 'ff' <= ... <= 'ffff'
138+
! CHECK-O0: CharacterCompareScalar1
139+
! CHECK-O0-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
140+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
141+
! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
129142
! CHECK-NEXT: cf.cond_br
130-
! CHECK: CharacterCompareScalar1
131-
! CHECK-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
143+
! CHECK-O0: CharacterCompareScalar1
144+
! CHECK-O0-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
145+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
146+
! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
132147
! CHECK-NEXT: cf.cond_br
133148
case ('ff':'ffff')
134149
nn = 20
135-
! CHECK: CharacterCompareScalar1
136-
! CHECK-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
150+
! == 'm'
151+
! CHECK-O0: CharacterCompareScalar1
152+
! CHECK-O0-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
153+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
154+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
137155
! CHECK-NEXT: cf.cond_br
138156
case ('m')
139157
nn = 30
140-
! CHECK: CharacterCompareScalar1
141-
! CHECK-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
158+
! == 'qq'
159+
! CHECK-O0: CharacterCompareScalar1
160+
! CHECK-O0-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
161+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
162+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
142163
! CHECK-NEXT: cf.cond_br
143164
case ('qq')
144165
nn = 40
145-
! CHECK: CharacterCompareScalar1
146-
! CHECK-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
166+
! >= 'x'
167+
! CHECK-O0: CharacterCompareScalar1
168+
! CHECK-O0-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
169+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
170+
! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
147171
! CHECK-NEXT: cf.cond_br
148172
case ('x':)
149173
nn = 50
@@ -159,14 +183,11 @@ subroutine scharacter1(s)
159183
! CHECK: %[[STR00:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3030"}
160184
! CHECK: %[[STR00_CONV:[0-9]+]] = fir.convert %[[STR00]]
161185

162-
! At -O1, lge() is lowered to various loops and "if" statements that work
163-
! with "00". It's not our goal to completely test lge() lowering here,
164-
! since this file is about testing SELECT CASE.
165-
! CHECK-O1: fir.do_loop
166-
! At -O0, we call runtime function for character comparison.
167186
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR00_CONV]]
168187
! CHECK-O0-NEXT: arith.cmpi sge, {{.*}}, %c0_i32 : i32
169-
! CHECK-O0-NEXT: cf.cond_br
188+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
189+
! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
190+
! CHECK-NEXT: cf.cond_br
170191
if (lge(s,'00')) then
171192

172193
! CHECK: fir.call @_FortranATrim
@@ -182,9 +203,11 @@ subroutine scharacter1(s)
182203
! CHECK: %[[STR88:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3838"}
183204

184205
! == '11'
185-
! CHECK: %[[STR11_CONV:[0-9]+]] = fir.convert %[[STR11]]
186-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR11_CONV]]
187-
! CHECK-NEXT: arith.cmpi eq
206+
! CHECK-O0: %[[STR11_CONV:[0-9]+]] = fir.convert %[[STR11]]
207+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR11_CONV]]
208+
! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
209+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
210+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
188211
! CHECK-NEXT: cf.cond_br
189212
select case(trim(s))
190213
case('11')
@@ -194,45 +217,59 @@ subroutine scharacter1(s)
194217
continue
195218

196219
! == '22'
197-
! CHECK: %[[STR22_CONV:[0-9]+]] = fir.convert %[[STR22]]
198-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR22_CONV]]
199-
! CHECK-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
220+
! CHECK-O0: %[[STR22_CONV:[0-9]+]] = fir.convert %[[STR22]]
221+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR22_CONV]]
222+
! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
223+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
224+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
200225
! CHECK-NEXT: cf.cond_br
201226
case('22')
202227
n = 2
203228

204229
! == '33'
205-
! CHECK: %[[STR33_CONV:[0-9]+]] = fir.convert %[[STR33]]
206-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR33_CONV]]
207-
! CHECK-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
230+
! CHECK-O0: %[[STR33_CONV:[0-9]+]] = fir.convert %[[STR33]]
231+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR33_CONV]]
232+
! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
233+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
234+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
208235
! CHECK-NEXT: cf.cond_br
209236
case('33')
210237
n = 3
211238

212239
! >= '44'
213-
! CHECK: %[[STR44_CONV:[0-9]+]] = fir.convert %[[STR44]]
214-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR44_CONV]]
215-
! CHECK-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
240+
! CHECK-O0: %[[STR44_CONV:[0-9]+]] = fir.convert %[[STR44]]
241+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR44_CONV]]
242+
! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
243+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
244+
! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
216245
! CHECK-NEXT: cf.cond_br
217246
! <= '55'
218-
! CHECK: %[[STR55_CONV:[0-9]+]] = fir.convert %[[STR55]]
219-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR55_CONV]]
220-
! CHECK-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32
247+
! CHECK-O0: %[[STR55_CONV:[0-9]+]] = fir.convert %[[STR55]]
248+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR55_CONV]]
249+
! CHECK-O0-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32
250+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
251+
! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
221252
! CHECK-NEXT: cf.cond_br
222253
! >= '66'
223-
! CHECK: %[[STR66_CONV:[0-9]+]] = fir.convert %[[STR66]]
224-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR66_CONV]]
225-
! CHECK-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
254+
! CHECK-O0: %[[STR66_CONV:[0-9]+]] = fir.convert %[[STR66]]
255+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR66_CONV]]
256+
! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
257+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
258+
! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
226259
! CHECK-NEXT: cf.cond_br
227260
! <= '77'
228-
! CHECK: %[[STR77_CONV:[0-9]+]] = fir.convert %[[STR77]]
229-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR77_CONV]]
230-
! CHECK-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32
261+
! CHECK-O0: %[[STR77_CONV:[0-9]+]] = fir.convert %[[STR77]]
262+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR77_CONV]]
263+
! CHECK-O0-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32
264+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
265+
! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
231266
! CHECK-NEXT: cf.cond_br
232267
! >= '88'
233-
! CHECK: %[[STR88_CONV:[0-9]+]] = fir.convert %[[STR88]]
234-
! CHECK: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR88_CONV]]
235-
! CHECK-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
268+
! CHECK-O0: %[[STR88_CONV:[0-9]+]] = fir.convert %[[STR88]]
269+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR88_CONV]]
270+
! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
271+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
272+
! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
236273
! CHECK-NEXT: cf.cond_br
237274
case('44':'55','66':'77','88':)
238275
n = 4
@@ -285,14 +322,20 @@ subroutine sempty(n)
285322
print*, n, 'i:case default'
286323
end select
287324
select case (char(ichar('0')+n))
288-
! CHECK: fir.call @_FortranACharacterCompareScalar1(
289-
! CHECK-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
325+
! == '1'
326+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1(
327+
! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
328+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
329+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
290330
! CHECK-NEXT: cf.cond_br
291331
case ('1')
292332
print*, n, 'c:case 1'
293333
case ('2')
294-
! CHECK: fir.call @_FortranACharacterCompareScalar1(
295-
! CHECK-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
334+
! == '2'
335+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1(
336+
! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
337+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
338+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
296339
! CHECK-NEXT: cf.cond_br
297340
! (empty) print*, n, 'c:case 2'
298341
case default
@@ -383,8 +426,11 @@ subroutine snested(str)
383426
if (present(str)) then
384427
! CHECK: fir.call @_FortranATrim
385428
select case (trim(str))
386-
! CHECK: fir.call @_FortranACharacterCompareScalar1
387-
! CHECK-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
429+
! == 'a'
430+
! CHECK-O0: fir.call @_FortranACharacterCompareScalar1
431+
! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
432+
! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
433+
! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
388434
case ('a')
389435
! CHECK-DAG: fir.store %c10_i32 to {{.*}} : !fir.ref<i32>
390436
num = 10

0 commit comments

Comments
 (0)