Index: flang/lib/Lower/OpenMP.cpp =================================================================== --- flang/lib/Lower/OpenMP.cpp +++ flang/lib/Lower/OpenMP.cpp @@ -1117,6 +1117,46 @@ // Generate the threadprivate value for the common block member. symThreadprivateValue = genCommonBlockMember(converter, sym, commonThreadprivateValue); + } else if (!var.isGlobal()) { + // Non-global variable which can be in threadprivate directive must be one + // variable in main program, and it has implicit SAVE attribute. Take it as + // with SAVE attribute, so to create GlobalOp for it to simplify the + // translation to LLVM IR. + mlir::Type ty = converter.genType(sym); + std::string globalName = converter.mangleName(sym); + mlir::StringAttr linkage = firOpBuilder.createInternalLinkage(); + fir::GlobalOp global = + firOpBuilder.createGlobal(currentLocation, ty, globalName, linkage); + + auto createInit = [&](std::function genInit) { + mlir::Region ®ion = global.getRegion(); + region.push_back(new mlir::Block); + mlir::Block &block = region.back(); + auto insertPt = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPointToStart(&block); + genInit(firOpBuilder); + firOpBuilder.restoreInsertionPoint(insertPt); + }; + + // Create default initialization for non-character scalar. + if (Fortran::semantics::IsAllocatableOrPointer(sym)) { + mlir::Type baseAddrType = ty.dyn_cast().getEleTy(); + createInit([&](fir::FirOpBuilder &b) { + mlir::Value nullAddr = + b.createNullConstant(currentLocation, baseAddrType); + mlir::Value box = b.create(currentLocation, ty, nullAddr); + b.create(currentLocation, box); + }); + } else { + createInit([&](fir::FirOpBuilder &b) { + mlir::Value undef = b.create(currentLocation, ty); + b.create(currentLocation, undef); + }); + } + mlir::Value symValue = firOpBuilder.create( + currentLocation, global.resultType(), global.getSymbol()); + symThreadprivateValue = firOpBuilder.create( + currentLocation, symValue.getType(), symValue); } else { mlir::Value symValue = converter.getSymbolAddress(sym); symThreadprivateValue = firOpBuilder.create( Index: flang/test/Lower/OpenMP/threadprivate-non-global.f90 =================================================================== --- /dev/null +++ flang/test/Lower/OpenMP/threadprivate-non-global.f90 @@ -0,0 +1,91 @@ +! This test checks lowering of OpenMP Threadprivate Directive. +! Test for non-character non-SAVEd non-initialized scalars with or without +! allocatable or pointer attribute in main program. + +!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s + +program test + integer :: x + real :: y + logical :: z + complex :: w + integer, pointer :: a + real, allocatable :: b + +!CHECK-DAG: [[ADDR0:%.*]] = fir.address_of(@_QFEa) : !fir.ref>> +!CHECK-DAG: [[NEWADDR0:%.*]] = omp.threadprivate [[ADDR0]] : !fir.ref>> -> !fir.ref>> +!CHECK-DAG: [[ADDR1:%.*]] = fir.address_of(@_QFEb) : !fir.ref>> +!CHECK-DAG: [[NEWADDR1:%.*]] = omp.threadprivate [[ADDR1]] : !fir.ref>> -> !fir.ref>> +!CHECK-DAG: [[ADDR2:%.*]] = fir.address_of(@_QFEw) : !fir.ref> +!CHECK-DAG: [[NEWADDR2:%.*]] = omp.threadprivate [[ADDR2]] : !fir.ref> -> !fir.ref> +!CHECK-DAG: [[ADDR3:%.*]] = fir.address_of(@_QFEx) : !fir.ref +!CHECK-DAG: [[NEWADDR3:%.*]] = omp.threadprivate [[ADDR3]] : !fir.ref -> !fir.ref +!CHECK-DAG: [[ADDR4:%.*]] = fir.address_of(@_QFEy) : !fir.ref +!CHECK-DAG: [[NEWADDR4:%.*]] = omp.threadprivate [[ADDR4]] : !fir.ref -> !fir.ref +!CHECK-DAG: [[ADDR5:%.*]] = fir.address_of(@_QFEz) : !fir.ref> +!CHECK-DAG: [[NEWADDR5:%.*]] = omp.threadprivate [[ADDR5]] : !fir.ref> -> !fir.ref> + !$omp threadprivate(x, y, z, w, a, b, w, a, b) + + call sub(a, b) + +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR3]] : !fir.ref +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR4]] : !fir.ref +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR5]] : !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR2]] : !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR0]] : !fir.ref>> +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR1]] : !fir.ref>> + print *, x, y, z, w, a, b + + !$omp parallel +!CHECK-DAG: [[ADDR68:%.*]] = omp.threadprivate [[ADDR0]] : !fir.ref>> -> !fir.ref>> +!CHECK-DAG: [[ADDR69:%.*]] = omp.threadprivate [[ADDR1]] : !fir.ref>> -> !fir.ref>> +!CHECK-DAG: [[ADDR70:%.*]] = omp.threadprivate [[ADDR2]] : !fir.ref> -> !fir.ref> +!CHECK-DAG: [[ADDR71:%.*]] = omp.threadprivate [[ADDR3]] : !fir.ref -> !fir.ref +!CHECK-DAG: [[ADDR72:%.*]] = omp.threadprivate [[ADDR4]] : !fir.ref -> !fir.ref +!CHECK-DAG: [[ADDR73:%.*]] = omp.threadprivate [[ADDR5]] : !fir.ref> -> !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[ADDR71]] : !fir.ref +!CHECK-DAG: %{{.*}} = fir.load [[ADDR72]] : !fir.ref +!CHECK-DAG: %{{.*}} = fir.load [[ADDR73]] : !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[ADDR70]] : !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[ADDR68]] : !fir.ref>> +!CHECK-DAG: %{{.*}} = fir.load [[ADDR69]] : !fir.ref>> + print *, x, y, z, w, a, b + !$omp end parallel + +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR3]] : !fir.ref +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR4]] : !fir.ref +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR5]] : !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR2]] : !fir.ref> +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR0]] : !fir.ref>> +!CHECK-DAG: %{{.*}} = fir.load [[NEWADDR1]] : !fir.ref>> + print *, x, y, z, w, a, b + +!CHECK: return + +!CHECK-DAG: fir.global internal @_QFEa : !fir.box> { +!CHECK-DAG: [[Z0:%.*]] = fir.zero_bits !fir.ptr +!CHECK-DAG: [[E0:%.*]] = fir.embox [[Z0]] : (!fir.ptr) -> !fir.box> +!CHECK-DAG: fir.has_value [[E0]] : !fir.box> +!CHECK-DAG: } +!CHECK-DAG: fir.global internal @_QFEb : !fir.box> { +!CHECK-DAG: [[Z1:%.*]] = fir.zero_bits !fir.heap +!CHECK-DAG: [[E1:%.*]] = fir.embox [[Z1]] : (!fir.heap) -> !fir.box> +!CHECK-DAG: fir.has_value [[E1]] : !fir.box> +!CHECK-DAG: } +!CHECK-DAG: fir.global internal @_QFEw : !fir.complex<4> { +!CHECK-DAG: [[Z2:%.*]] = fir.undefined !fir.complex<4> +!CHECK-DAG: fir.has_value [[Z2]] : !fir.complex<4> +!CHECK-DAG: } +!CHECK-DAG: fir.global internal @_QFEx : i32 { +!CHECK-DAG: [[Z3:%.*]] = fir.undefined i32 +!CHECK-DAG: fir.has_value [[Z3]] : i32 +!CHECK-DAG: } +!CHECK-DAG: fir.global internal @_QFEy : f32 { +!CHECK-DAG: [[Z4:%.*]] = fir.undefined f32 +!CHECK-DAG: fir.has_value [[Z4]] : f32 +!CHECK-DAG: } +!CHECK-DAG: fir.global internal @_QFEz : !fir.logical<4> { +!CHECK-DAG: [[Z5:%.*]] = fir.undefined !fir.logical<4> +!CHECK-DAG: fir.has_value [[Z5]] : !fir.logical<4> +!CHECK-DAG: } +end