! Note: character comparison is different: at -O0, flang-rt function is called,
! at -O1, inline character comparison is used.
! RUN: %flang_fc1 -emit-fir -O0 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-O0
! RUN: %flang_fc1 -emit-fir -O1 -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-O1

  !CHECK-LABEL: sinteger
  function sinteger(n)
    integer sinteger
    nn = -88
    ! CHECK-DAG: fir.select_case {{.*}} : i32
    ! CHECK-SAME: upper, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: point, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: #fir.point, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: #fir.interval, %c{{[0-9]+}}_i32, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: #fir.point, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: #fir.point, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: #fir.interval, %c{{[0-9]+}}_i32, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: #fir.lower, %c{{[0-9]+}}_i32,
    ! CHECK-SAME: unit
    select case(n)
    case (:1)
      nn = 1
    case (2)
      nn = 2
    case default
      nn = 0
    case (3)
      nn = 3
    case (4:5+1-1)
      nn = 4
    case (6)
      nn = 6
    case (7,8:15,21:)
      nn = 7
    end select
    sinteger = nn
  end

  ! CHECK-LABEL: slogical
  subroutine slogical(L)
    logical :: L
    n1 = 0
    n2 = 0
    n3 = 0
    n4 = 0
    n5 = 0
    n6 = 0
    n7 = 0
    n8 = 0

    select case (L)
    end select

    select case (L)
      ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false
      ! CHECK: cf.cond_br
      case (.false.)
        n2 = 1
    end select

    select case (L)
      ! CHECK: cf.cond_br
      case (.true.)
        n3 = 2
    end select

    select case (L)
      case default
        n4 = 3
    end select

    select case (L)
      ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false
      ! CHECK: cf.cond_br
      case (.false.)
        n5 = 1
      ! CHECK: cf.cond_br
      case (.true.)
        n5 = 2
    end select

    select case (L)
      ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false
      ! CHECK: cf.cond_br
      case (.false.)
        n6 = 1
      case default
        n6 = 3
    end select

    select case (L)
      ! CHECK: cf.cond_br
      case (.true.)
        n7 = 2
      case default
        n7 = 3
    end select

    select case (L)
      ! CHECK: arith.cmpi eq, %{{[0-9]+}}, %false
      ! CHECK: cf.cond_br
      case (.false.)
        n8 = 1
      ! CHECK: cf.cond_br
      case (.true.)
        n8 = 2
      ! CHECK-NOT: 888
      case default ! dead
        n8 = 888
    end select

    print*, n1, n2, n3, n4, n5, n6, n7, n8
  end

  ! CHECK-LABEL: scharacter
  subroutine scharacter(c)
    character(*) :: c
    nn = 0
    select case (c)
      case default
        nn = -1
      ! NOTE: common pattern of character comparison: at -O0, runtime function
      ! is called, followed by comparison of i32 values. At -O1 and above, 
      ! inline comparison code is done using loops. The comparison code ends
      ! with comparison of i8 values. At either -O0 or -O1, the comparison
      ! ends with a conditional branch. This comparison pattern is used
      ! throughout this file.
      !
      ! <= 'd'
      ! CHECK-O0: CharacterCompareScalar1
      ! CHECK-O0-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case (:'d')
        nn = 10
      ! 'ff' <= ... <= 'ffff'
      ! CHECK-O0: CharacterCompareScalar1
      ! CHECK-O0-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      ! CHECK-O0: CharacterCompareScalar1
      ! CHECK-O0-NEXT: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case ('ff':'ffff')
        nn = 20
      ! == 'm'
      ! CHECK-O0: CharacterCompareScalar1
      ! CHECK-O0-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case ('m')
        nn = 30
      ! == 'qq'
      ! CHECK-O0: CharacterCompareScalar1
      ! CHECK-O0-NEXT: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case ('qq')
        nn = 40
      ! >= 'x'
      ! CHECK-O0: CharacterCompareScalar1
      ! CHECK-O0-NEXT: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case ('x':)
        nn = 50
    end select
    print*, nn
  end

  ! CHECK-LABEL: func.func @_QPscharacter1
  subroutine scharacter1(s)
    character(len=3) :: s
    n = 0

    ! CHECK: %[[STR00:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3030"}
    ! CHECK: %[[STR00_CONV:[0-9]+]] = fir.convert %[[STR00]]

    ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR00_CONV]]
    ! CHECK-O0-NEXT: arith.cmpi sge, {{.*}}, %c0_i32 : i32
    ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
    ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
    ! CHECK-NEXT: cf.cond_br
    if (lge(s,'00')) then

      ! CHECK: fir.call @_FortranATrim

      ! All the strings in SELECT CASE
      ! CHECK: %[[STR11:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3131"}
      ! CHECK: %[[STR22:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3232"}
      ! CHECK: %[[STR33:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3333"}
      ! CHECK: %[[STR44:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3434"}
      ! CHECK: %[[STR55:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3535"}
      ! CHECK: %[[STR66:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3636"}
      ! CHECK: %[[STR77:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3737"}
      ! CHECK: %[[STR88:[0-9]+]] = fir.declare {{.*}} uniq_name = "_QQclX3838"}

      ! == '11'
      ! CHECK-O0: %[[STR11_CONV:[0-9]+]] = fir.convert %[[STR11]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR11_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      select case(trim(s))
      case('11')
        n = 1

      case default
        continue

      ! == '22'
      ! CHECK-O0: %[[STR22_CONV:[0-9]+]] = fir.convert %[[STR22]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR22_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case('22')
        n = 2

      ! == '33'
      ! CHECK-O0: %[[STR33_CONV:[0-9]+]] = fir.convert %[[STR33]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR33_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi eq,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case('33')
        n = 3

      ! >= '44'
      ! CHECK-O0: %[[STR44_CONV:[0-9]+]] = fir.convert %[[STR44]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR44_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      ! <= '55'
      ! CHECK-O0: %[[STR55_CONV:[0-9]+]] = fir.convert %[[STR55]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR55_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      ! >= '66'
      ! CHECK-O0: %[[STR66_CONV:[0-9]+]] = fir.convert %[[STR66]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR66_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      ! <= '77'
      ! CHECK-O0: %[[STR77_CONV:[0-9]+]] = fir.convert %[[STR77]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR77_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi sle,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sle, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      ! >= '88'
      ! CHECK-O0: %[[STR88_CONV:[0-9]+]] = fir.convert %[[STR88]]
      ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1({{.*}}, %[[STR88_CONV]]
      ! CHECK-O0-NEXT: arith.cmpi sge,{{.*}}, %c0_i32 : i32
      ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
      ! CHECK-O1: arith.cmpi sge, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
      ! CHECK-NEXT: cf.cond_br
      case('44':'55','66':'77','88':)
        n = 4
      end select
    end if
    print*, n
  end subroutine

  ! CHECK-LABEL: func @_QPscharacter2
  subroutine scharacter2(s)
    character(len=3) :: s
    ! CHECK: %[[N:[0-9]+]] = fir.declare {{.*}} {uniq_name = "_QFscharacter2En"}
    ! CHECK: fir.store %c-10_i32 to %[[N]] : !fir.ref<i32>
    n = -10
    ! CHECK: fir.call @_FortranATrim(
    select case(trim(s))
    case default
      ! CHECK: fir.store %c9_i32 to %[[N]] : !fir.ref<i32>
      n = 9
    end select

    ! CHECK: fir.call @_FortranAioBeginExternalListOutput(
    print*, n

    ! CHECK:  fir.store %c-2_i32 to %[[N]] : !fir.ref<i32>
    n = -2

    ! CHECK: fir.call @_FortranATrim(
    select case(trim(s))
    end select
    ! CHECK: fir.call @_FortranAioBeginExternalListOutput(
    print*, n
  end subroutine

  ! CHECK-LABEL: func @_QPsempty
  ! empty select case blocks
  subroutine sempty(n)
    !CHECK: fir.select_case {{.*}} : i32 [#fir.point, %c1_i32, ^bb1, #fir.point, %c2_i32, ^bb2, unit, ^bb3]
    select case (n)
      case (1)
        !CHECK: ^bb1:
        !CHECK: fir.call @_FortranAioBeginExternalListOutput(
        !CHECK: cf.br ^bb4
        print*, n, 'i:case 1'
      case (2)
        !CHECK: ^bb2:
        !CHECK-NEXT: cf.br ^bb4
      ! (empty) print*, n, 'i:case 2'
      case default
        print*, n, 'i:case default'
    end select
    select case (char(ichar('0')+n))
    ! == '1'
    ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1(
    ! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
    ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
    ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
    ! CHECK-NEXT: cf.cond_br
      case ('1')
        print*, n, 'c:case 1'
      case ('2')
    ! == '2'
    ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1(
    ! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
    ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
    ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
    ! CHECK-NEXT: cf.cond_br
      ! (empty) print*, n, 'c:case 2'
      case default
        print*, n, 'c:case default'
    end select
    ! CHECK: return
  end subroutine

  ! CHECK-LABEL: func @_QPsgoto
  ! select case with goto exit
  subroutine sgoto
    n = 0
    ! CHECK: cf.cond_br
    do i=1,8
      ! CHECK: fir.select_case %8 : i32 [#fir.upper, %c2_i32, ^bb{{.*}}, #fir.lower, %c5_i32, ^bb{{.*}}, unit, ^bb{{.*}}]
      select case(i)
      case (:2)
        ! CHECK-DAG: arith.muli {{.*}}, %c10_i32 : i32
        n = i * 10
      case (5:)
        ! CHECK-DAG: arith.muli {{.*}}, %c1000_i32 : i32
        n = i * 1000
        ! CHECK-DAG: arith.cmpi sle, {{.*}}, %c6_i32 : i32
        ! CHECK-NEXT: cf.cond_br
        if (i <= 6) goto 9
        ! CHECK-DAG: arith.muli {{.*}}, %c10000_i32 : i32
        n = i * 10000
      case default
        ! CHECK-DAG: arith.muli {{.*}}, %c100_i32 : i32
        n = i * 100
  9   end select
      print*, n
    enddo
    ! CHECK: return
  end

  ! CHECK-LABEL: func @_QPswhere
  subroutine swhere(num)
    implicit none

    integer, intent(in) :: num
    real, dimension(1) :: array

    array = 0.0

    ! CHECK: fir.select_case {{.*}} : i32 [#fir.point, %c1_i32, ^bb1, unit, ^bb2]
    select case (num)
    case (1)
      ! CHECK: fir.do_loop
      where (array >= 0.0)
        array = 42
      end where
    case default
      array = -1
    end select
    ! CHECK: cf.br ^bb3
    print*, array(1)
  end subroutine swhere

  ! CHECK-LABEL: func @_QPsforall
  subroutine sforall(num)
    implicit none

    integer, intent(in) :: num
    real, dimension(1) :: array
    integer :: i

    array = 0.0

    ! CHECK: fir.select_case {{.*}} : i32 [#fir.point, %c1_i32, ^bb1, unit, ^bb2]
    select case (num)
    case (1)
      ! CHECK: fir.do_loop
      forall (i = 1:size(array)) array(i) = 42
    case default
      array = -1
    end select
    ! CHECK: cf.br ^bb3
    print*, array(1)
  end subroutine sforall

  ! CHECK-LABEL: func @_QPsnested
  subroutine snested(str)
    character(*), optional :: str
    integer :: num

    ! CHECK: fir.is_present
    if (present(str)) then
      ! CHECK: fir.call @_FortranATrim
      select case (trim(str))
        ! == 'a'
        ! CHECK-O0: fir.call @_FortranACharacterCompareScalar1
        ! CHECK-O0-NEXT: arith.cmpi eq, {{.*}}, %c0_i32 : i32
        ! CHECK-O1: fir.do_loop {{.*}} -> (i8) {
        ! CHECK-O1: arith.cmpi eq, %{{[0-9]+}}, %c{{[0-9]+}}_i8 : i8
        case ('a')
          ! CHECK-DAG: fir.store %c10_i32 to {{.*}} : !fir.ref<i32>
          num = 10
        case default
          ! CHECK-DAG: fir.store %c20_i32 to {{.*}} : !fir.ref<i32>
          num = 20
      end select
    else
      ! CHECK-DAG: fir.store %c30_i32 to {{.*}} : !fir.ref<i32>
      num = 30
    end if
  end subroutine snested

  ! CHECK-LABEL: main
  program p
    integer sinteger, v(10)

    n = -10
    do j = 1, 4
      do k = 1, 10
        n = n + 1
        v(k) = sinteger(n)
      enddo
      ! expected output:  1 1 1 1 1 1 1 1 1 1
      !                   1 2 3 4 4 6 7 7 7 7
      !                   7 7 7 7 7 0 0 0 0 0
      !                   7 7 7 7 7 7 7 7 7 7
      print*, v
    enddo

    print*
    call slogical(.false.)    ! expected output:  0 1 0 3 1 1 3 1
    call slogical(.true.)     ! expected output:  0 0 2 3 2 3 2 2

    print*
    call scharacter('aa')     ! expected output: 10
    call scharacter('d')      ! expected output: 10
    call scharacter('f')      ! expected output: -1
    call scharacter('ff')     ! expected output: 20
    call scharacter('fff')    ! expected output: 20
    call scharacter('ffff')   ! expected output: 20
    call scharacter('fffff')  ! expected output: -1
    call scharacter('jj')     ! expected output: -1
    call scharacter('m')      ! expected output: 30
    call scharacter('q')      ! expected output: -1
    call scharacter('qq')     ! expected output: 40
    call scharacter('qqq')    ! expected output: -1
    call scharacter('vv')     ! expected output: -1
    call scharacter('xx')     ! expected output: 50
    call scharacter('zz')     ! expected output: 50

    print*
    call scharacter1('99 ')   ! expected output:  4
    call scharacter1('88 ')   ! expected output:  4
    call scharacter1('77 ')   ! expected output:  4
    call scharacter1('66 ')   ! expected output:  4
    call scharacter1('55 ')   ! expected output:  4
    call scharacter1('44 ')   ! expected output:  4
    call scharacter1('33 ')   ! expected output:  3
    call scharacter1('22 ')   ! expected output:  2
    call scharacter1('11 ')   ! expected output:  1
    call scharacter1('00 ')   ! expected output:  0
    call scharacter1('.  ')   ! expected output:  0
    call scharacter1('   ')   ! expected output:  0

    print*
    call scharacter2('99 ')   ! expected output:  9 -2
    call scharacter2('22 ')   ! expected output:  9 -2
    call scharacter2('.  ')   ! expected output:  9 -2
    call scharacter2('   ')   ! expected output:  9 -2

    print*
    call sempty(0)            ! expected output: 0 i:case default 0; c:case default
    call sempty(1)            ! expected output: 1 i:case 1; 1 c:case 1
    call sempty(2)            ! no output
    call sempty(3)            ! expected output: 3 i:case default; 3 c:case default

    print*
    call sgoto                ! expected output:  10 20 300 400 5000 6000 70000 80000

    print*
    call swhere(1)            ! expected output: 42.
    call sforall(1)           ! expected output: 42.
  end
