1! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s 2! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -o - %s | FileCheck %s 3! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fwrapv -o - %s | FileCheck %s --check-prefix=NO-NSW 4 5! Tests for unstructured loops. 6 7! NO-NSW-NOT: overflow<nsw> 8 9! Test a simple unstructured loop. Test for the existence of, 10! -> The initialization of the trip-count and loop-variable 11! -> The branch to the body or the exit inside the header 12! -> The increment of the trip-count and the loop-variable inside the body 13subroutine simple_unstructured() 14 integer :: i 15 do i=1,100 16 goto 404 17 404 continue 18 end do 19end subroutine 20! CHECK-LABEL: simple_unstructured 21! CHECK: %[[TRIP_VAR_REF:.*]] = fir.alloca i32 22! CHECK: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructuredEi"} 23! CHECK: %[[ONE:.*]] = arith.constant 1 : i32 24! CHECK: %[[HUNDRED:.*]] = arith.constant 100 : i32 25! CHECK: %[[STEP_ONE:.*]] = arith.constant 1 : i32 26! CHECK: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32 27! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP_ONE]] : i32 28! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP_ONE]] : i32 29! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32> 30! CHECK: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref<i32> 31! CHECK: cf.br ^[[HEADER:.*]] 32! CHECK: ^[[HEADER]]: 33! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32> 34! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32 35! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32 36! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] 37! CHECK: ^[[BODY]]: 38! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32> 39! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32 40! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32 41! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32> 42! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref<i32> 43! CHECK: %[[STEP_ONE_2:.*]] = arith.constant 1 : i32 44! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_ONE_2]] overflow<nsw> : i32 45! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref<i32> 46! CHECK: cf.br ^[[HEADER]] 47! CHECK: ^[[EXIT]]: 48! CHECK: return 49 50! Test an unstructured loop with a step. Mostly similar to the previous one. 51! Only difference is a non-unit step. 52subroutine simple_unstructured_with_step() 53 integer :: i 54 do i=1,100,2 55 goto 404 56 404 continue 57 end do 58end subroutine 59! CHECK-LABEL: simple_unstructured_with_step 60! CHECK: %[[TRIP_VAR_REF:.*]] = fir.alloca i32 61! CHECK: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructured_with_stepEi"} 62! CHECK: %[[ONE:.*]] = arith.constant 1 : i32 63! CHECK: %[[HUNDRED:.*]] = arith.constant 100 : i32 64! CHECK: %[[STEP:.*]] = arith.constant 2 : i32 65! CHECK: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32 66! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP]] : i32 67! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP]] : i32 68! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32> 69! CHECK: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref<i32> 70! CHECK: cf.br ^[[HEADER:.*]] 71! CHECK: ^[[HEADER]]: 72! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32> 73! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32 74! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32 75! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] 76! CHECK: ^[[BODY]]: 77! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32> 78! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32 79! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32 80! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32> 81! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref<i32> 82! CHECK: %[[STEP_2:.*]] = arith.constant 2 : i32 83! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_2]] overflow<nsw> : i32 84! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref<i32> 85! CHECK: cf.br ^[[HEADER]] 86! CHECK: ^[[EXIT]]: 87! CHECK: return 88 89! Test a three nested unstructured loop. Three nesting is the basic case where 90! we have loops that are neither innermost or outermost. 91subroutine nested_unstructured() 92 integer :: i, j, k 93 do i=1,100 94 do j=1,200 95 do k=1,300 96 goto 404 97 404 continue 98 end do 99 end do 100 end do 101end subroutine 102! CHECK-LABEL: nested_unstructured 103! CHECK: %[[TRIP_VAR_K_REF:.*]] = fir.alloca i32 104! CHECK: %[[TRIP_VAR_J_REF:.*]] = fir.alloca i32 105! CHECK: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32 106! CHECK: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_unstructuredEi"} 107! CHECK: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_unstructuredEj"} 108! CHECK: %[[LOOP_VAR_K_REF:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_unstructuredEk"} 109! CHECK: %[[I_START:.*]] = arith.constant 1 : i32 110! CHECK: %[[I_END:.*]] = arith.constant 100 : i32 111! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32 112! CHECK: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32 113! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32 114! CHECK: %[[TRIP_COUNT_I:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32 115! CHECK: fir.store %[[TRIP_COUNT_I]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 116! CHECK: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32> 117! CHECK: cf.br ^[[HEADER_I:.*]] 118! CHECK: ^[[HEADER_I]]: 119! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 120! CHECK: %[[ZERO_1:.*]] = arith.constant 0 : i32 121! CHECK: %[[COND_I:.*]] = arith.cmpi sgt, %[[TRIP_VAR_I]], %[[ZERO_1]] : i32 122! CHECK: cf.cond_br %[[COND_I]], ^[[BODY_I:.*]], ^[[EXIT_I:.*]] 123! CHECK: ^[[BODY_I]]: 124! CHECK: %[[J_START:.*]] = arith.constant 1 : i32 125! CHECK: %[[J_END:.*]] = arith.constant 200 : i32 126! CHECK: %[[J_STEP:.*]] = arith.constant 1 : i32 127! CHECK: %[[TMP3:.*]] = arith.subi %[[J_END]], %[[J_START]] : i32 128! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[J_STEP]] : i32 129! CHECK: %[[TRIP_COUNT_J:.*]] = arith.divsi %[[TMP4]], %[[J_STEP]] : i32 130! CHECK: fir.store %[[TRIP_COUNT_J]] to %[[TRIP_VAR_J_REF]] : !fir.ref<i32> 131! CHECK: fir.store %[[J_START]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32> 132! CHECK: cf.br ^[[HEADER_J:.*]] 133! CHECK: ^[[HEADER_J]]: 134! CHECK: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref<i32> 135! CHECK: %[[ZERO_2:.*]] = arith.constant 0 : i32 136! CHECK: %[[COND_J:.*]] = arith.cmpi sgt, %[[TRIP_VAR_J]], %[[ZERO_2]] : i32 137! CHECK: cf.cond_br %[[COND_J]], ^[[BODY_J:.*]], ^[[EXIT_J:.*]] 138! CHECK: ^[[BODY_J]]: 139! CHECK: %[[K_START:.*]] = arith.constant 1 : i32 140! CHECK: %[[K_END:.*]] = arith.constant 300 : i32 141! CHECK: %[[K_STEP:.*]] = arith.constant 1 : i32 142! CHECK: %[[TMP3:.*]] = arith.subi %[[K_END]], %[[K_START]] : i32 143! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[K_STEP]] : i32 144! CHECK: %[[TRIP_COUNT_K:.*]] = arith.divsi %[[TMP4]], %[[K_STEP]] : i32 145! CHECK: fir.store %[[TRIP_COUNT_K]] to %[[TRIP_VAR_K_REF]] : !fir.ref<i32> 146! CHECK: fir.store %[[K_START]] to %[[LOOP_VAR_K_REF]] : !fir.ref<i32> 147! CHECK: cf.br ^[[HEADER_K:.*]] 148! CHECK: ^[[HEADER_K]]: 149! CHECK: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref<i32> 150! CHECK: %[[ZERO_2:.*]] = arith.constant 0 : i32 151! CHECK: %[[COND_K:.*]] = arith.cmpi sgt, %[[TRIP_VAR_K]], %[[ZERO_2]] : i32 152! CHECK: cf.cond_br %[[COND_K]], ^[[BODY_K:.*]], ^[[EXIT_K:.*]] 153! CHECK: ^[[BODY_K]]: 154! CHECK: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref<i32> 155! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32 156! CHECK: %[[TRIP_VAR_K_NEXT:.*]] = arith.subi %[[TRIP_VAR_K]], %[[ONE_1]] : i32 157! CHECK: fir.store %[[TRIP_VAR_K_NEXT]] to %[[TRIP_VAR_K_REF]] : !fir.ref<i32> 158! CHECK: %[[LOOP_VAR_K:.*]] = fir.load %[[LOOP_VAR_K_REF]] : !fir.ref<i32> 159! CHECK: %[[K_STEP_2:.*]] = arith.constant 1 : i32 160! CHECK: %[[LOOP_VAR_K_NEXT:.*]] = arith.addi %[[LOOP_VAR_K]], %[[K_STEP_2]] overflow<nsw> : i32 161! CHECK: fir.store %[[LOOP_VAR_K_NEXT]] to %[[LOOP_VAR_K_REF]] : !fir.ref<i32> 162! CHECK: cf.br ^[[HEADER_K]] 163! CHECK: ^[[EXIT_K]]: 164! CHECK: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref<i32> 165! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32 166! CHECK: %[[TRIP_VAR_J_NEXT:.*]] = arith.subi %[[TRIP_VAR_J]], %[[ONE_1]] : i32 167! CHECK: fir.store %[[TRIP_VAR_J_NEXT]] to %[[TRIP_VAR_J_REF]] : !fir.ref<i32> 168! CHECK: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref<i32> 169! CHECK: %[[J_STEP_2:.*]] = arith.constant 1 : i32 170! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %[[J_STEP_2]] overflow<nsw> : i32 171! CHECK: fir.store %[[LOOP_VAR_J_NEXT]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32> 172! CHECK: cf.br ^[[HEADER_J]] 173! CHECK: ^[[EXIT_J]]: 174! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 175! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32 176! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[ONE_1]] : i32 177! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 178! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32> 179! CHECK: %[[I_STEP_2:.*]] = arith.constant 1 : i32 180! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] overflow<nsw> : i32 181! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32> 182! CHECK: cf.br ^[[HEADER_I]] 183! CHECK: ^[[EXIT_I]]: 184! CHECK: return 185 186! Test the existence of a structured loop inside an unstructured loop. 187! Only minimal checks are inserted for the structured loop. 188subroutine nested_structured_in_unstructured() 189 integer :: i, j 190 do i=1,100 191 do j=1,100 192 end do 193 goto 404 194 404 continue 195 end do 196end subroutine 197! CHECK-LABEL: nested_structured_in_unstructured 198! CHECK: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32 199! CHECK: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_structured_in_unstructuredEi"} 200! CHECK: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_structured_in_unstructuredEj"} 201! CHECK: %[[I_START:.*]] = arith.constant 1 : i32 202! CHECK: %[[I_END:.*]] = arith.constant 100 : i32 203! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32 204! CHECK: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32 205! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32 206! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32 207! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 208! CHECK: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32> 209! CHECK: cf.br ^[[HEADER:.*]] 210! CHECK: ^[[HEADER]]: 211! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 212! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32 213! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32 214! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]] 215! CHECK: ^[[BODY]]: 216! CHECK: %{{.*}} = fir.do_loop %[[J_INDEX:[^ ]*]] = 217! CHECK-SAME: %{{.*}} to %{{.*}} step %[[ST:[^ ]*]] 218! CHECK-SAME: iter_args(%[[J_IV:.*]] = %{{.*}}) -> (index, i32) { 219! CHECK: fir.store %[[J_IV]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32> 220! CHECK: %[[J_INDEX_NEXT:.*]] = arith.addi %[[J_INDEX]], %[[ST]] overflow<nsw> : index 221! CHECK: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref<i32> 222! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %{{[^ ]*}} overflow<nsw> : i32 223! CHECK: } 224! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 225! CHECK: %[[C1_3:.*]] = arith.constant 1 : i32 226! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32 227! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32> 228! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32> 229! CHECK: %[[I_STEP_2:.*]] = arith.constant 1 : i32 230! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] overflow<nsw> : i32 231! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32> 232! CHECK: cf.br ^[[HEADER]] 233! CHECK: ^[[EXIT]]: 234! CHECK: return 235