1! RUN: bbc -emit-fir -o - %s | FileCheck %s 2! RUN: %flang_fc1 -emit-fir -o - %s | FileCheck %s 3 4! Simple tests for structured ordered loops with loop-control. 5! Tests the structure of the loop, storage to index variable and return and 6! storage of the final value of the index variable. 7 8! Test a simple loop with the final value of the index variable read outside the loop 9! CHECK-LABEL: simple_loop 10subroutine simple_loop 11 ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_loopEi"} 12 integer :: i 13 14 ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 15 ! CHECK: %[[C1_CVT:.*]] = fir.convert %c1_i32 : (i32) -> index 16 ! CHECK: %[[C5:.*]] = arith.constant 5 : i32 17 ! CHECK: %[[C5_CVT:.*]] = fir.convert %c5_i32 : (i32) -> index 18 ! CHECK: %[[C1:.*]] = arith.constant 1 : index 19 ! CHECK: %[[LI_RES:.*]] = fir.do_loop %[[LI:.*]] = %[[C1_CVT]] to %[[C5_CVT]] step %[[C1]] -> index { 20 do i=1,5 21 ! CHECK: %[[LI_CVT:.*]] = fir.convert %[[LI]] : (index) -> i32 22 ! CHECK: fir.store %[[LI_CVT]] to %[[I_REF]] : !fir.ref<i32> 23 ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[C1]] : index 24 ! CHECK: fir.result %[[LI_NEXT]] : index 25 ! CHECK: } 26 end do 27 ! CHECK: %[[LI_RES_CVT:.*]] = fir.convert %[[LI_RES]] : (index) -> i32 28 ! CHECK: fir.store %[[LI_RES_CVT]] to %[[I_REF]] : !fir.ref<i32> 29 ! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32> 30 ! CHECK: %{{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[I]]) : (!fir.ref<i8>, i32) -> i1 31 print *, i 32end subroutine 33 34! Test a 2-nested loop with a body composed of a reduction. Values are read from a 2d array. 35! CHECK-LABEL: nested_loop 36subroutine nested_loop 37 ! CHECK: %[[ARR_REF:.*]] = fir.alloca !fir.array<5x5xi32> {bindc_name = "arr", uniq_name = "_QFnested_loopEarr"} 38 ! CHECK: %[[ASUM_REF:.*]] = fir.alloca i32 {bindc_name = "asum", uniq_name = "_QFnested_loopEasum"} 39 ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_loopEi"} 40 ! CHECK: %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_loopEj"} 41 integer :: asum, arr(5,5) 42 integer :: i, j 43 asum = 0 44 ! CHECK: %[[S_I:.*]] = arith.constant 1 : i32 45 ! CHECK: %[[S_I_CVT:.*]] = fir.convert %[[S_I]] : (i32) -> index 46 ! CHECK: %[[E_I:.*]] = arith.constant 5 : i32 47 ! CHECK: %[[E_I_CVT:.*]] = fir.convert %[[E_I]] : (i32) -> index 48 ! CHECK: %[[ST_I:.*]] = arith.constant 1 : index 49 ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:.*]] = %[[S_I_CVT]] to %[[E_I_CVT]] step %[[ST_I]] -> index { 50 do i=1,5 51 ! CHECK: %[[LI_CVT:.*]] = fir.convert %[[LI]] : (index) -> i32 52 ! CHECK: fir.store %[[LI_CVT]] to %[[I_REF]] : !fir.ref<i32> 53 ! CHECK: %[[S_J:.*]] = arith.constant 1 : i32 54 ! CHECK: %[[S_J_CVT:.*]] = fir.convert %[[S_J]] : (i32) -> index 55 ! CHECK: %[[E_J:.*]] = arith.constant 5 : i32 56 ! CHECK: %[[E_J_CVT:.*]] = fir.convert %[[E_J]] : (i32) -> index 57 ! CHECK: %[[ST_J:.*]] = arith.constant 1 : index 58 ! CHECK: %[[J_RES:.*]] = fir.do_loop %[[LJ:.*]] = %[[S_J_CVT]] to %[[E_J_CVT]] step %[[ST_J]] -> index { 59 do j=1,5 60 ! CHECK: %[[LJ_CVT:.*]] = fir.convert %[[LJ]] : (index) -> i32 61 ! CHECK: fir.store %[[LJ_CVT]] to %[[J_REF]] : !fir.ref<i32> 62 ! CHECK: %[[ASUM:.*]] = fir.load %[[ASUM_REF]] : !fir.ref<i32> 63 ! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32> 64 ! CHECK: %[[I_CVT:.*]] = fir.convert %[[I]] : (i32) -> i64 65 ! CHECK: %[[C1_I:.*]] = arith.constant 1 : i64 66 ! CHECK: %[[I_INDX:.*]] = arith.subi %[[I_CVT]], %[[C1_I]] : i64 67 ! CHECK: %[[J:.*]] = fir.load %[[J_REF]] : !fir.ref<i32> 68 ! CHECK: %[[J_CVT:.*]] = fir.convert %[[J]] : (i32) -> i64 69 ! CHECK: %[[C1_J:.*]] = arith.constant 1 : i64 70 ! CHECK: %[[J_INDX:.*]] = arith.subi %[[J_CVT]], %[[C1_J]] : i64 71 ! CHECK: %[[ARR_IJ_REF:.*]] = fir.coordinate_of %[[ARR_REF]], %[[I_INDX]], %[[J_INDX]] : (!fir.ref<!fir.array<5x5xi32>>, i64, i64) -> !fir.ref<i32> 72 ! CHECK: %[[ARR_VAL:.*]] = fir.load %[[ARR_IJ_REF]] : !fir.ref<i32> 73 ! CHECK: %[[ASUM_NEW:.*]] = arith.addi %[[ASUM]], %[[ARR_VAL]] : i32 74 ! CHECK: fir.store %[[ASUM_NEW]] to %[[ASUM_REF]] : !fir.ref<i32> 75 asum = asum + arr(i,j) 76 ! CHECK: %[[LJ_NEXT:.*]] = arith.addi %[[LJ]], %[[ST_J]] : index 77 ! CHECK: fir.result %[[LJ_NEXT]] : index 78 ! CHECK: } 79 end do 80 ! CHECK: %[[J_RES_CVT:.*]] = fir.convert %[[J_RES]] : (index) -> i32 81 ! CHECK: fir.store %[[J_RES_CVT]] to %[[J_REF]] : !fir.ref<i32> 82 ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_I]] : index 83 ! CHECK: fir.result %[[LI_NEXT]] : index 84 ! CHECK: } 85 end do 86 ! CHECK: %[[I_RES_CVT:.*]] = fir.convert %[[I_RES]] : (index) -> i32 87 ! CHECK: fir.store %[[I_RES_CVT]] to %[[I_REF]] : !fir.ref<i32> 88end subroutine 89 90! Test a downcounting loop 91! CHECK-LABEL: down_counting_loop 92subroutine down_counting_loop() 93 integer :: i 94 ! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFdown_counting_loopEi"} 95 96 ! CHECK: %[[C5:.*]] = arith.constant 5 : i32 97 ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index 98 ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 99 ! CHECK: %[[C1_CVT:.*]] = fir.convert %[[C1]] : (i32) -> index 100 ! CHECK: %[[CMINUS1:.*]] = arith.constant -1 : i32 101 ! CHECK: %[[CMINUS1_STEP_CVT:.*]] = fir.convert %[[CMINUS1]] : (i32) -> index 102 ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:.*]] = %[[C5_CVT]] to %[[C1_CVT]] step %[[CMINUS1_STEP_CVT]] -> index { 103 do i=5,1,-1 104 ! CHECK: %[[LI_CVT:.*]] = fir.convert %[[LI]] : (index) -> i32 105 ! CHECK: fir.store %[[LI_CVT]] to %[[I_REF]] : !fir.ref<i32> 106 ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[CMINUS1_STEP_CVT]] : index 107 ! CHECK: fir.result %[[LI_NEXT]] : index 108 ! CHECK: } 109 end do 110 ! CHECK: %[[I_RES_CVT:.*]] = fir.convert %[[I_RES]] : (index) -> i32 111 ! CHECK: fir.store %[[I_RES_CVT]] to %[[I_REF]] : !fir.ref<i32> 112end subroutine 113 114! Test a general loop with a variable step 115! CHECK-LABEL: loop_with_variable_step 116! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "st"}) { 117subroutine loop_with_variable_step(s,e,st) 118 integer :: s, e, st 119 ! CHECK: %[[S:.*]] = fir.load %[[S_REF]] : !fir.ref<i32> 120 ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index 121 ! CHECK: %[[E:.*]] = fir.load %[[E_REF]] : !fir.ref<i32> 122 ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index 123 ! CHECK: %[[ST:.*]] = fir.load %[[ST_REF]] : !fir.ref<i32> 124 ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index 125 ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:.*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] -> index { 126 do i=s,e,st 127 ! CHECK: %[[LI_CVT:.*]] = fir.convert %[[LI]] : (index) -> i32 128 ! CHECK: fir.store %[[LI_CVT]] to %[[I_REF]] : !fir.ref<i32> 129 ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT]] : index 130 ! CHECK: fir.result %[[LI_NEXT]] : index 131 ! CHECK: } 132 end do 133 ! CHECK: %[[I_RES_CVT:.*]] = fir.convert %[[I_RES]] : (index) -> i32 134 ! CHECK: fir.store %[[I_RES_CVT]] to %[[I_REF]] : !fir.ref<i32> 135end subroutine 136 137! Test usage of pointer variables as index, start, end and step variables 138! CHECK-LABEL: loop_with_pointer_variables 139! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "s", fir.target}, %[[E_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "e", fir.target}, %[[ST_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "st", fir.target}) { 140subroutine loop_with_pointer_variables(s,e,st) 141! CHECK: %[[E_PTR_REF:.*]] = fir.alloca !fir.ptr<i32> {uniq_name = "_QFloop_with_pointer_variablesEeptr.addr"} 142! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", fir.target, uniq_name = "_QFloop_with_pointer_variablesEi"} 143! CHECK: %[[I_PTR_REF:.*]] = fir.alloca !fir.ptr<i32> {uniq_name = "_QFloop_with_pointer_variablesEiptr.addr"} 144! CHECK: %[[S_PTR_REF:.*]] = fir.alloca !fir.ptr<i32> {uniq_name = "_QFloop_with_pointer_variablesEsptr.addr"} 145! CHECK: %[[ST_PTR_REF:.*]] = fir.alloca !fir.ptr<i32> {uniq_name = "_QFloop_with_pointer_variablesEstptr.addr"} 146 integer, target :: i 147 integer, target :: s, e, st 148 integer, pointer :: iptr, sptr, eptr, stptr 149 150! CHECK: %[[I_PTR:.*]] = fir.convert %[[I_REF]] : (!fir.ref<i32>) -> !fir.ptr<i32> 151! CHECK: fir.store %[[I_PTR]] to %[[I_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 152! CHECK: %[[S_PTR:.*]] = fir.convert %[[S_REF]] : (!fir.ref<i32>) -> !fir.ptr<i32> 153! CHECK: fir.store %[[S_PTR]] to %[[S_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 154! CHECK: %[[E_PTR:.*]] = fir.convert %[[E_REF]] : (!fir.ref<i32>) -> !fir.ptr<i32> 155! CHECK: fir.store %[[E_PTR]] to %[[E_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 156! CHECK: %[[ST_PTR:.*]] = fir.convert %[[ST_REF]] : (!fir.ref<i32>) -> !fir.ptr<i32> 157! CHECK: fir.store %[[ST_PTR]] to %[[ST_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 158 iptr => i 159 sptr => s 160 eptr => e 161 stptr => st 162 163! CHECK: %[[I_PTR:.*]] = fir.load %[[I_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 164! CHECK: %[[S_PTR:.*]] = fir.load %[[S_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 165! CHECK: %[[S:.*]] = fir.load %[[S_PTR]] : !fir.ptr<i32> 166! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index 167! CHECK: %[[E_PTR:.*]] = fir.load %[[E_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 168! CHECK: %[[E:.*]] = fir.load %[[E_PTR]] : !fir.ptr<i32> 169! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index 170! CHECK: %[[ST_PTR:.*]] = fir.load %[[ST_PTR_REF]] : !fir.ref<!fir.ptr<i32>> 171! CHECK: %[[ST:.*]] = fir.load %[[ST_PTR]] : !fir.ptr<i32> 172! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index 173! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:.*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] -> index { 174 do iptr=sptr,eptr,stptr 175! CHECK: %[[LI_CVT:.*]] = fir.convert %[[LI]] : (index) -> i32 176! CHECK: fir.store %[[LI_CVT]] to %[[I_PTR]] : !fir.ptr<i32> 177! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT]] : index 178! CHECK: fir.result %[[LI_NEXT]] : index 179 end do 180! CHECK: } 181! CHECK: %[[I_RES_CVT:.*]] = fir.convert %[[I_RES]] : (index) -> i32 182! CHECK: fir.store %[[I_RES_CVT:.*]] to %[[I_PTR]] : !fir.ptr<i32> 183end subroutine 184 185! Test usage of non-default integer kind for loop control and loop index variable 186! CHECK-LABEL: loop_with_non_default_integer 187! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref<i64> {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref<i64> {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref<i64> {fir.bindc_name = "st"}) { 188subroutine loop_with_non_default_integer(s,e,st) 189 ! CHECK: %[[I_REF:.*]] = fir.alloca i64 {bindc_name = "i", uniq_name = "_QFloop_with_non_default_integerEi"} 190 integer(kind=8):: i 191 ! CHECK: %[[S:.*]] = fir.load %[[S_REF]] : !fir.ref<i64> 192 ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i64) -> index 193 ! CHECK: %[[E:.*]] = fir.load %[[E_REF]] : !fir.ref<i64> 194 ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i64) -> index 195 ! CHECK: %[[ST:.*]] = fir.load %[[ST_REF]] : !fir.ref<i64> 196 ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i64) -> index 197 integer(kind=8) :: s, e, st 198 199 ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:.*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] -> index { 200 do i=s,e,st 201 ! CHECK: %[[LI_CVT:.*]] = fir.convert %[[LI]] : (index) -> i64 202 ! CHECK: fir.store %[[LI_CVT]] to %[[I_REF]] : !fir.ref<i64> 203 ! CHECK: %[[LI_NEXT:.*]] = arith.addi %[[LI]], %[[ST_CVT]] : index 204 ! CHECK: fir.result %[[LI_NEXT]] : index 205 end do 206 ! CHECK: } 207 ! CHECK: %[[I_RES_CVT:.*]] = fir.convert %[[I_RES]] : (index) -> i64 208 ! CHECK: fir.store %[[I_RES_CVT]] to %[[I_REF]] : !fir.ref<i64> 209end subroutine 210 211! Test real loop control. 212! CHECK-LABEL: loop_with_real_control 213! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref<f32> {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref<f32> {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref<f32> {fir.bindc_name = "st"}) { 214subroutine loop_with_real_control(s,e,st) 215 ! CHECK-DAG: %[[INDEX_REF:.*]] = fir.alloca index 216 ! CHECK-DAG: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFloop_with_real_controlEx"} 217 ! CHECK-DAG: %[[S:.*]] = fir.load %[[S_REF]] : !fir.ref<f32> 218 ! CHECK-DAG: %[[E:.*]] = fir.load %[[E_REF]] : !fir.ref<f32> 219 ! CHECK-DAG: %[[ST:.*]] = fir.load %[[ST_REF]] : !fir.ref<f32> 220 real :: x, s, e, st 221 222 ! CHECK: %[[DIFF:.*]] = arith.subf %[[E]], %[[S]] : f32 223 ! CHECK: %[[RANGE:.*]] = arith.addf %[[DIFF]], %[[ST]] : f32 224 ! CHECK: %[[HIGH:.*]] = arith.divf %[[RANGE]], %[[ST]] : f32 225 ! CHECK: %[[HIGH_INDEX:.*]] = fir.convert %[[HIGH]] : (f32) -> index 226 ! CHECK: fir.store %[[HIGH_INDEX]] to %[[INDEX_REF]] : !fir.ref<index> 227 ! CHECK: fir.store %[[S]] to %[[X_REF]] : !fir.ref<f32> 228 229 ! CHECK: br ^[[HDR:.*]] 230 ! CHECK: ^[[HDR]]: // 2 preds: ^{{.*}}, ^[[EXIT:.*]] 231 ! CHECK-DAG: %[[INDEX:.*]] = fir.load %[[INDEX_REF]] : !fir.ref<index> 232 ! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 233 ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[INDEX]], %[[C0]] : index 234 ! CHECK: cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] 235 do x=s,e,st 236 ! CHECK: ^[[BODY]]: // pred: ^[[HDR]] 237 ! CHECK-DAG: %[[INDEX2:.*]] = fir.load %[[INDEX_REF]] : !fir.ref<index> 238 ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 239 ! CHECK: %[[INC:.*]] = arith.subi %[[INDEX2]], %[[C1]] : index 240 ! CHECK: fir.store %[[INC]] to %[[INDEX_REF]] : !fir.ref<index> 241 ! CHECK: %[[X2:.*]] = fir.load %[[X_REF]] : !fir.ref<f32> 242 ! CHECK: %[[XINC:.*]] = arith.addf %[[X2]], %[[ST]] : f32 243 ! CHECK: fir.store %[[XINC]] to %[[X_REF]] : !fir.ref<f32> 244 ! CHECK: br ^[[HDR]] 245 end do 246end subroutine 247