| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s | ||
|
|
||
| bool cond(); | ||
| void foo(); | ||
|
|
||
| void test1() { | ||
| do { | ||
| } while (cond()); | ||
| } | ||
| // CHECK: define spir_func void @_Z5test1v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: do.body: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: do.cond: | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test2() { | ||
| do { | ||
| foo(); | ||
| } while (cond()); | ||
| } | ||
| // CHECK: define spir_func void @_Z5test2v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: do.body: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: do.cond: | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test3() { | ||
| do { | ||
| if (cond()) | ||
| foo(); | ||
| } while (cond()); | ||
| } | ||
| // CHECK: define spir_func void @_Z5test3v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: do.body: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: do.cond: | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test4() { | ||
| do { | ||
| if (cond()) { | ||
| foo(); | ||
| break; | ||
| } | ||
| } while (cond()); | ||
| } | ||
| // CHECK: define spir_func void @_Z5test4v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: do.body: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: do.cond: | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test5() { | ||
| do { | ||
| while (cond()) { | ||
| if (cond()) { | ||
| foo(); | ||
| break; | ||
| } | ||
| } | ||
| } while (cond()); | ||
| } | ||
| // CHECK: define spir_func void @_Z5test5v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: do.body: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T2]]) ] | ||
| // CHECK: do.cond: | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| // CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } | ||
| // CHECK-DAG: attributes [[A3]] = { {{.*}}convergent{{.*}} } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s | ||
|
|
||
| bool cond(); | ||
| bool cond2(); | ||
| void foo(); | ||
|
|
||
| void test1() { | ||
| for (;;) { | ||
| foo(); | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test1v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test2() { | ||
| for (;cond();) { | ||
| foo(); | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test2v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: for.body: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test3() { | ||
| for (cond();;) { | ||
| foo(); | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test3v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test4() { | ||
| for (cond();cond2();) { | ||
| foo(); | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test4v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z5cond2v() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: for.body: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test5() { | ||
| for (cond();cond2();foo()) { | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test5v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z5cond2v() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: for.inc: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test6() { | ||
| for (cond();cond2();foo()) { | ||
| if (cond()) { | ||
| foo(); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test6v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z5cond2v() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: for.body: | ||
| // CHECK: [[C1:%[a-zA-Z0-9]+]] = call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: br i1 [[C1]], label %if.then, label %if.end | ||
| // CHECK: if.then: | ||
| // CHECK call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: br label %for.end | ||
| // CHECK: if.end: | ||
| // CHECK: br label %for.inc | ||
| // CHECK: for.inc: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test7() { | ||
| for (cond();;) { | ||
| for (cond();;) { | ||
| foo(); | ||
| } | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test7v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: for.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: for.cond3: | ||
| // CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: call spir_func void @_Z3foov() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T2]]) ] | ||
|
|
||
| // CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } | ||
| // CHECK-DAG: attributes [[A3]] = { {{.*}}convergent{{.*}} } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s | ||
|
|
||
| bool cond(); | ||
| void foo(); | ||
|
|
||
| void test1() { | ||
| while (cond()) { | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test1v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3:#[0-9]+]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test2() { | ||
| while (cond()) { | ||
| foo(); | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test2v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: while.body: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
|
|
||
| void test3() { | ||
| while (cond()) { | ||
| if (cond()) | ||
| break; | ||
| foo(); | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test3v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: br label %while.end | ||
| // CHECK: if.end: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: br label %while.cond | ||
|
|
||
| void test4() { | ||
| while (cond()) { | ||
| if (cond()) { | ||
| foo(); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test4v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: br label %while.end | ||
| // CHECK: if.end: | ||
| // CHECK: br label %while.cond | ||
|
|
||
| void test5() { | ||
| while (cond()) { | ||
| while (cond()) { | ||
| if (cond()) { | ||
| foo(); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test5v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: while.cond2: | ||
| // CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T2]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T2]]) ] | ||
| // CHECK: br label %while.end | ||
|
|
||
| void test6() { | ||
| while (cond()) { | ||
| while (cond()) { | ||
| } | ||
|
|
||
| if (cond()) { | ||
| foo(); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| // CHECK: define spir_func void @_Z5test6v() [[A0:#[0-9]+]] { | ||
| // CHECK: entry: | ||
| // CHECK: [[T0:%[0-9]+]] = call token @llvm.experimental.convergence.entry() | ||
| // CHECK: while.cond: | ||
| // CHECK: [[T1:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T0]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: while.cond2: | ||
| // CHECK: [[T2:%[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: call spir_func noundef i1 @_Z4condv() [[A3]] [ "convergencectrl"(token [[T2]]) ] | ||
| // CHECK: if.then: | ||
| // CHECK: call spir_func void @_Z3foov() [[A3]] [ "convergencectrl"(token [[T1]]) ] | ||
| // CHECK: br label %while.end | ||
|
|
||
| // CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } | ||
| // CHECK-DAG: attributes [[A3]] = { {{.*}}convergent{{.*}} } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple x86_64-pc-linux -fsyntax-only -verify -Wno-c++17-extensions | ||
| // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple x86_64-windows-msvc -fsyntax-only -verify=msvc -Wno-c++17-extensions | ||
| // expected-no-diagnostics | ||
|
|
||
| // Check we return non-zero values for supported attributes as per | ||
| // wg21.link/P2552 | ||
| static_assert(__has_cpp_attribute(assume)); | ||
|
|
||
| // The standard does not prescribe a behavior for [[carries_dependency]] | ||
|
|
||
| static_assert(__has_cpp_attribute(deprecated)); | ||
| static_assert(__has_cpp_attribute(fallthrough)); | ||
| static_assert(__has_cpp_attribute(likely)); | ||
| static_assert(__has_cpp_attribute(unlikely)); | ||
| static_assert(__has_cpp_attribute(maybe_unused)); | ||
| static_assert(__has_cpp_attribute(nodiscard)); | ||
| static_assert(__has_cpp_attribute(noreturn)); | ||
|
|
||
| // We do not support [[no_unique_address]] in MSVC emulation mode | ||
| static_assert(__has_cpp_attribute(no_unique_address)); // msvc-error {{static assertion failed}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| ! DEFINE: %{resource_dir} = %S/Inputs/resource_dir | ||
| ! RUN: %flang -print-resource-dir -resource-dir=%{resource_dir}.. \ | ||
| ! RUN: | FileCheck -check-prefix=PRINT-RESOURCE-DIR -DFILE=%{resource_dir} %s | ||
| ! PRINT-RESOURCE-DIR: [[FILE]] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Test hlfir.where masked region cleanup lowering (the freemem in the tests). | ||
| // RUN: fir-opt %s --lower-hlfir-ordered-assignments | FileCheck %s | ||
|
|
||
| func.func @loop_cleanup(%mask : !fir.ref<!fir.array<2x!fir.logical<4>>>, %x : !fir.ref<!fir.array<2xf32>>, %y : !fir.ref<!fir.array<2xf32>>) { | ||
| hlfir.where { | ||
| %1 = fir.allocmem !fir.array<10xi32> | ||
| hlfir.yield %mask : !fir.ref<!fir.array<2x!fir.logical<4>>> cleanup { | ||
| fir.freemem %1 : !fir.heap<!fir.array<10xi32>> | ||
| } | ||
| } do { | ||
| hlfir.region_assign { | ||
| %1 = fir.allocmem !fir.array<1xi32> | ||
| %2 = fir.allocmem !fir.array<2xi32> | ||
| hlfir.yield %x : !fir.ref<!fir.array<2xf32>> cleanup { | ||
| fir.freemem %2 : !fir.heap<!fir.array<2xi32>> | ||
| fir.freemem %1 : !fir.heap<!fir.array<1xi32>> | ||
| } | ||
| } to { | ||
| %1 = fir.allocmem !fir.array<3xi32> | ||
| %2 = fir.allocmem !fir.array<4xi32> | ||
| hlfir.yield %y : !fir.ref<!fir.array<2xf32>> cleanup { | ||
| fir.freemem %2 : !fir.heap<!fir.array<4xi32>> | ||
| fir.freemem %1 : !fir.heap<!fir.array<3xi32>> | ||
| } | ||
| } | ||
| } | ||
| return | ||
| } | ||
| // CHECK-LABEL: func.func @loop_cleanup( | ||
| // CHECK: %[[VAL_3:.*]] = fir.allocmem !fir.array<10xi32> | ||
| // CHECK: fir.do_loop | ||
| // CHECK: fir.if | ||
| // CHECK: %[[VAL_11:.*]] = fir.allocmem !fir.array<1xi32> | ||
| // CHECK: %[[VAL_12:.*]] = fir.allocmem !fir.array<2xi32> | ||
| // CHECK: %[[VAL_14:.*]] = fir.allocmem !fir.array<3xi32> | ||
| // CHECK: %[[VAL_15:.*]] = fir.allocmem !fir.array<4xi32> | ||
| // CHECK: hlfir.assign | ||
| // CHECK: fir.freemem %[[VAL_15]] : !fir.heap<!fir.array<4xi32>> | ||
| // CHECK: fir.freemem %[[VAL_14]] : !fir.heap<!fir.array<3xi32>> | ||
| // CHECK: fir.freemem %[[VAL_12]] : !fir.heap<!fir.array<2xi32>> | ||
| // CHECK: fir.freemem %[[VAL_11]] : !fir.heap<!fir.array<1xi32>> | ||
| // CHECK: } | ||
| // CHECK: } | ||
| // CHECK: fir.freemem %[[VAL_3]] : !fir.heap<!fir.array<10xi32>> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| ! Test that scalar expressions are not hoisted from WHERE loops | ||
| ! when they do not appear | ||
| ! RUN: bbc -hlfir -o - -pass-pipeline="builtin.module(lower-hlfir-ordered-assignments)" %s | FileCheck %s | ||
|
|
||
| subroutine do_not_hoist_div(n, mask, a) | ||
| integer :: a(10), n | ||
| logical :: mask(10) | ||
| where(mask) a=1/n | ||
| end subroutine | ||
| ! CHECK-LABEL: func.func @_QPdo_not_hoist_div( | ||
| ! CHECK-NOT: arith.divsi | ||
| ! CHECK: fir.do_loop {{.*}} { | ||
| ! CHECK: fir.if {{.*}} { | ||
| ! CHECK: arith.divsi | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
|
|
||
| subroutine do_not_hoist_optional(n, mask, a) | ||
| integer :: a(10) | ||
| integer, optional :: n | ||
| logical :: mask(10) | ||
| where(mask) a=n | ||
| end subroutine | ||
| ! CHECK-LABEL: func.func @_QPdo_not_hoist_optional( | ||
| ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare {{.*}}"_QFdo_not_hoist_optionalEn" | ||
| ! CHECK-NOT: fir.load %[[VAL_9]] | ||
| ! CHECK: fir.do_loop {{.*}} { | ||
| ! CHECK: fir.if {{.*}} { | ||
| ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
|
|
||
| subroutine hoist_function(n, mask, a) | ||
| integer :: a(10, 10) | ||
| integer, optional :: n | ||
| logical :: mask(10, 10) | ||
| forall (i=1:10) | ||
| where(mask(i, :)) a(i,:)=ihoist_me(i) | ||
| end forall | ||
| end subroutine | ||
| ! CHECK-LABEL: func.func @_QPhoist_function( | ||
| ! CHECK: fir.do_loop {{.*}} { | ||
| ! CHECK: fir.call @_QPihoist_me | ||
| ! CHECK: fir.do_loop {{.*}} { | ||
| ! CHECK: fir.if %{{.*}} { | ||
| ! CHECK-NOT: fir.call @_QPihoist_me | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK-NOT: fir.call @_QPihoist_me |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| ! Test lowering of non elemental calls and there inputs inside WHERE | ||
| ! constructs. These must be lowered inside hlfir.exactly_once so that | ||
| ! they are properly hoisted once the loops are materialized and | ||
| ! expression evaluations are scheduled. | ||
| ! RUN: bbc -emit-hlfir -o - %s | FileCheck %s | ||
|
|
||
| subroutine test_where(a, b, c) | ||
| real, dimension(:) :: a, b, c | ||
| interface | ||
| function logical_func1() | ||
| logical :: logical_func1(100) | ||
| end function | ||
| function logical_func2() | ||
| logical :: logical_func2(100) | ||
| end function | ||
| real elemental function elem_func(x) | ||
| real, intent(in) :: x | ||
| end function | ||
| end interface | ||
| where (logical_func1()) | ||
| a = b + real_func(a+b+real_func2()) + elem_func(a) | ||
| elsewhere(logical_func2()) | ||
| a(1:ifoo()) = c | ||
| end where | ||
| end subroutine | ||
| ! CHECK-LABEL: func.func @_QPtest_where( | ||
| ! CHECK: hlfir.where { | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: %[[VAL_17:.*]] = fir.call @llvm.stacksave.p0() fastmath<contract> : () -> !fir.ref<i8> | ||
| ! CHECK: %[[VAL_19:.*]] = fir.call @_QPlogical_func1() fastmath<contract> : () -> !fir.array<100x!fir.logical<4>> | ||
| ! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { | ||
| ! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_17]]) fastmath<contract> : (!fir.ref<i8>) -> () | ||
| ! CHECK: } | ||
| ! CHECK: } do { | ||
| ! CHECK: hlfir.region_assign { | ||
| ! CHECK: %[[VAL_24:.*]] = hlfir.exactly_once : f32 { | ||
| ! CHECK: %[[VAL_28:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: } | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: %[[VAL_35:.*]] = fir.call @_QPreal_func2() fastmath<contract> : () -> f32 | ||
| ! CHECK: %[[VAL_36:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: ^bb0(%[[VAL_37:.*]]: index): | ||
| ! CHECK: %[[VAL_38:.*]] = hlfir.apply %[[VAL_28]], %[[VAL_37]] : (!hlfir.expr<?xf32>, index) -> f32 | ||
| ! CHECK: %[[VAL_39:.*]] = arith.addf %[[VAL_38]], %[[VAL_35]] fastmath<contract> : f32 | ||
| ! CHECK: hlfir.yield_element %[[VAL_39]] : f32 | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_41:.*]] = fir.call @_QPreal_func | ||
| ! CHECK: hlfir.yield %[[VAL_41]] : f32 cleanup { | ||
| ! CHECK: hlfir.destroy %[[VAL_36]] : !hlfir.expr<?xf32> | ||
| ! CHECK: hlfir.destroy %[[VAL_28]] : !hlfir.expr<?xf32> | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_45:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: arith.addf | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_53:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: fir.call @_QPelem_func | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_57:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: arith.addf | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.yield %[[VAL_57]] : !hlfir.expr<?xf32> cleanup { | ||
| ! CHECK: hlfir.destroy %[[VAL_57]] : !hlfir.expr<?xf32> | ||
| ! CHECK: hlfir.destroy %[[VAL_53]] : !hlfir.expr<?xf32> | ||
| ! CHECK: hlfir.destroy %[[VAL_45]] : !hlfir.expr<?xf32> | ||
| ! CHECK: } | ||
| ! CHECK: } to { | ||
| ! CHECK: hlfir.yield %{{.*}} : !fir.box<!fir.array<?xf32>> | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.elsewhere mask { | ||
| ! CHECK: %[[VAL_62:.*]] = hlfir.exactly_once : !hlfir.expr<100x!fir.logical<4>> { | ||
| ! CHECK: %[[VAL_72:.*]] = fir.call @llvm.stacksave.p0() fastmath<contract> : () -> !fir.ref<i8> | ||
| ! CHECK: fir.call @_QPlogical_func2() fastmath<contract> : () -> !fir.array<100x!fir.logical<4>> | ||
| ! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { | ||
| ! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_72]]) fastmath<contract> : (!fir.ref<i8>) -> () | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.yield %[[VAL_62]] : !hlfir.expr<100x!fir.logical<4>> | ||
| ! CHECK: } do { | ||
| ! CHECK: hlfir.region_assign { | ||
| ! CHECK: hlfir.yield %{{.*}} : !fir.box<!fir.array<?xf32>> | ||
| ! CHECK: } to { | ||
| ! CHECK: %[[VAL_80:.*]] = hlfir.exactly_once : i32 { | ||
| ! CHECK: %[[VAL_81:.*]] = fir.call @_QPifoo() fastmath<contract> : () -> i32 | ||
| ! CHECK: hlfir.yield %[[VAL_81]] : i32 | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.yield %{{.*}} : !fir.box<!fir.array<?xf32>> | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: return | ||
| ! CHECK: } | ||
|
|
||
| subroutine test_where_in_forall(a, b, c) | ||
| real, dimension(:, :) :: a, b, c | ||
| interface | ||
| pure function pure_logical_func1() | ||
| logical :: pure_logical_func1(100) | ||
| end function | ||
| pure function pure_logical_func2() | ||
| logical :: pure_logical_func2(100) | ||
| end function | ||
| real pure elemental function pure_elem_func(x) | ||
| real, intent(in) :: x | ||
| end function | ||
| integer pure function pure_ifoo() | ||
| end function | ||
| end interface | ||
| forall(i=1:10) | ||
| where (pure_logical_func1()) | ||
| a(2*i, :) = b(i, :) + pure_real_func(a(i,:)+b(i,:)+pure_real_func2()) + pure_elem_func(a(i,:)) | ||
| elsewhere(pure_logical_func2()) | ||
| a(2*i, 1:pure_ifoo()) = c(i, :) | ||
| end where | ||
| end forall | ||
| end subroutine | ||
| ! CHECK-LABEL: func.func @_QPtest_where_in_forall( | ||
| ! CHECK: hlfir.forall lb { | ||
| ! CHECK: hlfir.yield %{{.*}} : i32 | ||
| ! CHECK: } ub { | ||
| ! CHECK: hlfir.yield %{{.*}} : i32 | ||
| ! CHECK: } (%[[VAL_10:.*]]: i32) { | ||
| ! CHECK: %[[VAL_11:.*]] = hlfir.forall_index "i" %[[VAL_10]] : (i32) -> !fir.ref<i32> | ||
| ! CHECK: hlfir.where { | ||
| ! CHECK: %[[VAL_21:.*]] = fir.call @llvm.stacksave.p0() fastmath<contract> : () -> !fir.ref<i8> | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: %[[VAL_23:.*]] = fir.call @_QPpure_logical_func1() fastmath<contract> : () -> !fir.array<100x!fir.logical<4>> | ||
| ! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { | ||
| ! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_21]]) fastmath<contract> : (!fir.ref<i8>) -> () | ||
| ! CHECK: } | ||
| ! CHECK: } do { | ||
| ! CHECK: hlfir.region_assign { | ||
| ! CHECK: %[[VAL_41:.*]] = hlfir.designate | ||
| ! CHECK: %[[VAL_42:.*]] = hlfir.exactly_once : f32 { | ||
| ! CHECK: hlfir.designate | ||
| ! CHECK: hlfir.designate | ||
| ! CHECK: %[[VAL_71:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: arith.addf | ||
| ! CHECK: } | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: %[[VAL_78:.*]] = fir.call @_QPpure_real_func2() fastmath<contract> : () -> f32 | ||
| ! CHECK: %[[VAL_79:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: arith.addf | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_84:.*]] = fir.call @_QPpure_real_func( | ||
| ! CHECK: hlfir.yield %[[VAL_84]] : f32 cleanup { | ||
| ! CHECK: hlfir.destroy %[[VAL_79]] : !hlfir.expr<?xf32> | ||
| ! CHECK: hlfir.destroy %[[VAL_71]] : !hlfir.expr<?xf32> | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_85:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: arith.addf | ||
| ! CHECK: } | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: %[[VAL_104:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: ^bb0(%[[VAL_105:.*]]: index): | ||
| ! CHECK-NOT: hlfir.exactly_once | ||
| ! CHECK: fir.call @_QPpure_elem_func | ||
| ! CHECK: } | ||
| ! CHECK: %[[VAL_108:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xf32> { | ||
| ! CHECK: arith.addf | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.yield %[[VAL_108]] : !hlfir.expr<?xf32> cleanup { | ||
| ! CHECK: hlfir.destroy %[[VAL_108]] : !hlfir.expr<?xf32> | ||
| ! CHECK: hlfir.destroy %[[VAL_104]] : !hlfir.expr<?xf32> | ||
| ! CHECK: hlfir.destroy %[[VAL_85]] : !hlfir.expr<?xf32> | ||
| ! CHECK: } | ||
| ! CHECK: } to { | ||
| ! CHECK: hlfir.designate | ||
| ! CHECK: hlfir.yield %{{.*}} : !fir.box<!fir.array<?xf32>> | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.elsewhere mask { | ||
| ! CHECK: %[[VAL_129:.*]] = hlfir.exactly_once : !hlfir.expr<100x!fir.logical<4>> { | ||
| ! CHECK: %[[VAL_139:.*]] = fir.call @llvm.stacksave.p0() fastmath<contract> : () -> !fir.ref<i8> | ||
| ! CHECK: %[[VAL_141:.*]] = fir.call @_QPpure_logical_func2() fastmath<contract> : () -> !fir.array<100x!fir.logical<4>> | ||
| ! CHECK: hlfir.yield %{{.*}} : !hlfir.expr<100x!fir.logical<4>> cleanup { | ||
| ! CHECK: fir.call @llvm.stackrestore.p0(%[[VAL_139]]) fastmath<contract> : (!fir.ref<i8>) -> () | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.yield %[[VAL_129]] : !hlfir.expr<100x!fir.logical<4>> | ||
| ! CHECK: } do { | ||
| ! CHECK: hlfir.region_assign { | ||
| ! CHECK: hlfir.designate | ||
| ! CHECK: hlfir.yield %{{.*}} : !fir.box<!fir.array<?xf32>> | ||
| ! CHECK: } to { | ||
| ! CHECK: %[[VAL_165:.*]] = hlfir.exactly_once : i32 { | ||
| ! CHECK: %[[VAL_166:.*]] = fir.call @_QPpure_ifoo() fastmath<contract> : () -> i32 | ||
| ! CHECK: hlfir.yield %[[VAL_166]] : i32 | ||
| ! CHECK: } | ||
| ! CHECK: hlfir.designate | ||
| ! CHECK: hlfir.yield %{{.*}} : !fir.box<!fir.array<?xf32>> | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: } | ||
| ! CHECK: return | ||
| ! CHECK: } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| //===-- Definition of macros from errno.h ---------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_HDR_ERRNO_MACROS_H | ||
| #define LLVM_LIBC_HDR_ERRNO_MACROS_H | ||
|
|
||
| #ifdef LIBC_FULL_BUILD | ||
|
|
||
| #ifdef __linux__ | ||
| #include <linux/errno.h> | ||
|
|
||
| #include "llvm-libc-macros/error-number-macros.h" | ||
| #else // __linux__ | ||
| #include "llvm-libc-macros/generic-error-number-macros.h" | ||
| #endif | ||
|
|
||
| #else // Overlay mode | ||
|
|
||
| #include <errno.h> | ||
|
|
||
| #endif // LLVM_LIBC_FULL_BUILD | ||
|
|
||
| #endif // LLVM_LIBC_HDR_ERRNO_MACROS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #ifndef LLVM_LIBC_MACROS_ERROR_NUMBER_MACROS_H | ||
| #define LLVM_LIBC_MACROS_ERROR_NUMBER_MACROS_H | ||
|
|
||
| #ifdef __linux__ | ||
| #include "linux/error-number-macros.h" | ||
| #endif | ||
|
|
||
| #endif // LLVM_LIBC_MACROS_ERROR_NUMBER_MACROS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #ifndef LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H | ||
| #define LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H | ||
|
|
||
| #if defined(__mips__) | ||
| #include "mips/error-number-macros.h" | ||
|
|
||
| #elif defined(__sparc__) | ||
| #include "sparc/error-number-macros.h" | ||
|
|
||
| #else | ||
| #ifndef ECANCELED | ||
| #define ECANCELED 125 | ||
| #endif // ECANCELED | ||
|
|
||
| #ifndef EOWNERDEAD | ||
| #define EOWNERDEAD 130 | ||
| #endif // EOWNERDEAD | ||
|
|
||
| #ifndef ENOTRECOVERABLE | ||
| #define ENOTRECOVERABLE 131 | ||
| #endif // ENOTRECOVERABLE | ||
|
|
||
| #ifndef ERFKILL | ||
| #define ERFKILL 132 | ||
| #endif // ERFKILL | ||
|
|
||
| #ifndef EHWPOISON | ||
| #define EHWPOISON 133 | ||
| #endif // EHWPOISON | ||
| #endif | ||
|
|
||
| #endif // LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| add_header( | ||
| error_number_macros | ||
| HDR | ||
| error-number-macros.h | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #ifndef LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H | ||
| #define LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H | ||
|
|
||
| #ifndef ECANCELED | ||
| #define ECANCELED 158 | ||
| #endif // ECANCELED | ||
|
|
||
| #ifndef EOWNERDEAD | ||
| #define EOWNERDEAD 165 | ||
| #endif // EOWNERDEAD | ||
|
|
||
| #ifndef ENOTRECOVERABLE | ||
| #define ENOTRECOVERABLE 166 | ||
| #endif // ENOTRECOVERABLE | ||
|
|
||
| #ifndef ERFKILL | ||
| #define ERFKILL 167 | ||
| #endif // ERFKILL | ||
|
|
||
| #ifndef EHWPOISON | ||
| #define EHWPOISON 168 | ||
| #endif // EHWPOISON | ||
|
|
||
| #endif // LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| add_header( | ||
| error_number_macros | ||
| HDR | ||
| error-number-macros.h | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #ifndef LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H | ||
| #define LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H | ||
|
|
||
| #ifndef ECANCELED | ||
| #define ECANCELED 127 | ||
| #endif // ECANCELED | ||
|
|
||
| #ifndef EOWNERDEAD | ||
| #define EOWNERDEAD 132 | ||
| #endif // EOWNERDEAD | ||
|
|
||
| #ifndef ENOTRECOVERABLE | ||
| #define ENOTRECOVERABLE 133 | ||
| #endif // ENOTRECOVERABLE | ||
|
|
||
| #ifndef ERFKILL | ||
| #define ERFKILL 134 | ||
| #endif // ERFKILL | ||
|
|
||
| #ifndef EHWPOISON | ||
| #define EHWPOISON 135 | ||
| #endif // EHWPOISON | ||
|
|
||
| #endif // LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H |