llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (ShashwathiNavada)

<details>
<summary>Changes</summary>

When a mapper is declared with an iterator variable inside the map clause, it 
results in unintended behavior due to the iterator being implicitly created but 
left uninitialized.
Testcase:

```
typedef struct myvec{
    size_t len;
    double *data;
} myvec_t;

#pragma omp declare mapper(id:myvec_t v) map( iterator( 
iterator_variable=0:v.len), tofrom: v.data[iterator_variable]) 

int main() 
{ 
    int errors = 0;
   myvec_t s;
   #pragma omp target map(mapper(id), to:s)
     {
     }
  return 0;
}
```
The error we get while compiling this is:
```
/usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld: 
/tmp/test-f70647.o: in function `.omp_mapper._ZTS5myvec.id':
test.cpp:(.text+0x21a): undefined reference to `iterator_variable'
/llvm-project/install/bin/clang-linker-wrapper: error: 'ld' failed
clang++: error: linker command failed with exit code 1 (use -v to see 
invocation)
```
 This patch tries to fix this by initializing the iterator variable to a null 
constant.

---
Full diff: https://github.com/llvm/llvm-project/pull/141507.diff


4 Files Affected:

- (modified) clang/include/clang/Basic/Attr.td (+7) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+5) 
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+2) 
- (modified) clang/test/OpenMP/declare_mapper_codegen.cpp (+102) 


``````````diff
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index ccd13a4cca4dd..cc629443e9b2d 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4461,6 +4461,13 @@ def OMPCaptureKind : Attr {
   }];
 }
 
+def OMPIterator : Attr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [InternalOnly];
+}
+
 def OMPReferencedVar : Attr {
   // This attribute has no spellings as it is only ever created implicitly.
   let Spellings = [];
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index ec01c87c13b1d..994327f690689 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2969,6 +2969,11 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction 
&CGF,
 
   llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
 
+  if (VD->hasAttr<OMPIteratorAttr>()) {
+  llvm::GlobalVariable *Var = llvm::dyn_cast<llvm::GlobalVariable>(V);
+  Var->setInitializer(CGF.CGM.EmitNullConstant(E->getType()));
+  }
+
   if (VD->getTLSKind() != VarDecl::TLS_None)
     V = CGF.Builder.CreateThreadLocalAddress(V);
 
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index f16f841d62edd..1756c20ce486c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -24476,6 +24476,8 @@ ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
         VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
                         D.DeclIdent, DeclTy, TInfo, SC_None);
     VD->setImplicit();
+    VD->addAttr(OMPIteratorAttr::CreateImplicit(
+        Context, SourceRange(StartLoc)));
     if (S) {
       // Check for conflicting previous declaration.
       DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
diff --git a/clang/test/OpenMP/declare_mapper_codegen.cpp 
b/clang/test/OpenMP/declare_mapper_codegen.cpp
index 81453223b2a27..7dc32d0ae12ff 100644
--- a/clang/test/OpenMP/declare_mapper_codegen.cpp
+++ b/clang/test/OpenMP/declare_mapper_codegen.cpp
@@ -1055,4 +1055,106 @@ void foo(int a){
 
 #endif // CK4
 
+///==========================================================================///
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp -fopenmp-version=52 
-fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple 
powerpc64le-unknown-unknown -emit-llvm -femit-all-decls -disable-llvm-passes %s 
-o - | FileCheck --check-prefix CK5 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp -fopenmp-version=52 
-fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple 
powerpc64le-unknown-unknown -emit-pch -femit-all-decls -disable-llvm-passes -o 
%t %s
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-version=52 -fopenmp 
-fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown 
-emit-llvm -femit-all-decls -disable-llvm-passes %s -o - | FileCheck 
--check-prefix CK5 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp -fopenmp-version=52 
-fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple 
i386-unknown-unknown -emit-pch -femit-all-decls -disable-llvm-passes -o %t %s
+
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-version=52 
-fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple 
powerpc64le-unknown-unknown -emit-llvm -femit-all-decls -disable-llvm-passes %s 
-o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -fopenmp-version=52 
-fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple 
powerpc64le-unknown-unknown -emit-pch -femit-all-decls -disable-llvm-passes -o 
%t %s
+// RUN: %clang_cc1 -DCK5 -verify -fopenmp-simd -fopenmp-version=52 
-fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown 
-emit-llvm -femit-all-decls -disable-llvm-passes %s -o - | FileCheck 
--check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK5 -fopenmp-simd -fopenmp-version=52 
-fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple 
i386-unknown-unknown -emit-pch -femit-all-decls -disable-llvm-passes -o %t %s
+
+#ifdef CK5
+typedef struct myvec {
+    int a;
+    double *b;
+} myvec_t;
+
+#pragma omp declare mapper(id: myvec_t v) map(iterator(it=0:v.a), tofrom: 
v.b[it])
+// CK5: @[[ITER:[a-zA-Z0-9_]+]] = global i32 0, align 4
+
+void foo(){ 
+  myvec_t s;
+  #pragma omp target map(mapper(id), to:s)
+  {
+  }
+}
+
+// CK5: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*myvec[.]id]](ptr 
noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], 
i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
+// CK5-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], {{.*}}
+// CK5-DAG: [[PTREND:%.+]] = getelementptr %struct.myvec, ptr [[BEGIN]], i64 
[[SIZE]]
+// CK5-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
+// CK5-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
+// CK5-DAG: [[PTRANDOBJ:%.+]] = and i64 [[TYPE]], 16
+// CK5-DAG: [[ISPTRANDOBJ:%.+]] = icmp ne i64 [[PTRANDOBJ]], 0
+// CK5-DAG: [[CMPA:%.+]] = and i1 [[PTRSNE]], [[ISPTRANDOBJ]]
+// CK5-DAG: [[CMP:%.+]] = or i1 [[ISARRAY]], [[CMPA]]
+// CK5-DAG: [[TYPEDEL:%.+]] = and i64 [[TYPE]], 8
+// CK5-DAG: [[ISNOTDEL:%.+]] = icmp eq i64 [[TYPEDEL]], 0
+// CK5-DAG: [[CMP1:%.+]] = and i1 [[CMP]], [[ISNOTDEL]]
+// CK5: br i1 [[CMP1]], label %[[INITEVALDEL:[^,]+]], label %[[LHEAD:[^,]+]]
+
+// CK5: [[INITEVALDEL]]
+// CK5-DAG: [[ARRSIZE:%.+]] = mul nuw i64 [[SIZE]], {{.*}}
+
+// Remove movement mappings and mark as implicit
+// CK5-DAG: [[ITYPE:%.+]] = and i64 [[TYPE]], -4
+// CK5-DAG: [[ITYPE1:%.+]] = or i64 [[ITYPE]], 512
+// CK5: call void @__tgt_push_mapper_component(ptr [[HANDLE]], ptr [[BPTR]], 
ptr [[BEGIN]], i64 [[ARRSIZE]], i64 [[ITYPE1]], {{.*}})
+// CK5: br label %[[LHEAD:[^,]+]]
+
+// CK5: [[LHEAD]]
+// CK5: [[ISEMPTY:%.+]] = icmp eq ptr [[BEGIN]], [[PTREND]]
+// CK5: br i1 [[ISEMPTY]], label %[[DONE:[^,]+]], label %[[LBODY:[^,]+]]
+// CK5: [[LBODY]]
+// CK5: [[PTR:%.+]] = phi ptr [ [[BEGIN]], %{{.+}} ], [ [[PTRNEXT:%.+]], 
%[[LCORRECT:[^,]+]] ]
+// CK5-DAG: [[ABEGIN:%.+]] = getelementptr inbounds nuw %struct.myvec, ptr 
[[PTR]], i32 0, i32 1
+// CK5-DAG: load i32, ptr @[[ITER]], align 4
+// CK5-DAG: [[PRESIZE:%.+]] = call i64 @__tgt_mapper_num_components(ptr 
[[HANDLE]])
+// CK5-DAG: [[SHIPRESIZE:%.+]] = shl i64 [[PRESIZE]], 48
+// CK5-DAG: [[MEMBERTYPE:%.+]] = add nuw i64 0, [[SHIPRESIZE]]
+// CK5-DAG: [[TYPETF:%.+]] = and i64 [[TYPE]], 3
+// CK5-DAG: [[ISALLOC:%.+]] = icmp eq i64 [[TYPETF]], 0
+// CK5-DAG: br i1 [[ISALLOC]], label %[[ALLOC:[^,]+]], label 
%[[ALLOCELSE:[^,]+]]
+// CK5-DAG: [[ALLOC]]
+// CK5-DAG: [[ALLOCTYPE:%.+]] = and i64 [[MEMBERTYPE]], -4
+// CK5-DAG: br label %[[TYEND:[^,]+]]
+// CK5-DAG: [[ALLOCELSE]]
+// CK5-DAG: [[ISTO:%.+]] = icmp eq i64 [[TYPETF]], 1
+// CK5-DAG: br i1 [[ISTO]], label %[[TO:[^,]+]], label %[[TOELSE:[^,]+]]
+// CK5-DAG: [[TO]]
+// CK5-DAG: [[TOTYPE:%.+]] = and i64 [[MEMBERTYPE]], -3
+// CK5-DAG: br label %[[TYEND]]
+// CK5-DAG: [[TOELSE]]
+// CK5-DAG: [[ISFROM:%.+]] = icmp eq i64 [[TYPETF]], 2
+// CK5-DAG: br i1 [[ISFROM]], label %[[FROM:[^,]+]], label %[[TYEND]]
+// CK5-DAG: [[FROM]]
+// CK5-DAG: [[FROMTYPE:%.+]] = and i64 [[MEMBERTYPE]], -2
+// CK5-DAG: br label %[[TYEND]]
+// CK5-DAG: [[TYEND]]
+// CK5-DAG: [[TYPE1:%.+]] = phi i64 [ [[ALLOCTYPE]], %[[ALLOC]] ], [ 
[[TOTYPE]], %[[TO]] ], [ [[FROMTYPE]], %[[FROM]] ], [ [[MEMBERTYPE]], 
%[[TOELSE]] ]
+// CK5: call void @__tgt_push_mapper_component(ptr [[HANDLE]], ptr [[PTR]], 
ptr [[ABEGIN]], i64 {{.*}}, i64 [[TYPE1]], {{.*}})
+// CK5: [[PTRNEXT]] = getelementptr %struct.myvec, ptr [[PTR]], i32 1
+// CK5: [[ISDONE:%.+]] = icmp eq ptr [[PTRNEXT]], [[PTREND]]
+// CK5: br i1 [[ISDONE]], label %[[LEXIT:[^,]+]], label %[[LBODY]]
+
+// CK5: [[LEXIT]]
+// CK5: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
+// CK5: [[TYPEDEL:%.+]] = and i64 [[TYPE]], 8
+// CK5: [[ISNOTDEL:%.+]] = icmp ne i64 [[TYPEDEL]], {{.*}}
+// CK5: [[CMP1:%.+]] = and i1 [[ISARRAY]], [[ISNOTDEL]]
+// CK5-DAG: [[ARRSIZE:%.+]] = mul nuw i64 [[SIZE]], {{.*}}
+
+// Remove movement mappings and mark as implicit
+// CK5-DAG: [[DTYPE:%.+]] = and i64 [[TYPE]], -4
+// CK5-DAG: [[DTYPE1:%.+]] = or i64 [[DTYPE]], 512
+// CK5: call void @__tgt_push_mapper_component(ptr [[HANDLE]], ptr [[BPTR]], 
ptr [[BEGIN]], i64 [[ARRSIZE]], i64 [[DTYPE1]], {{.*}})
+// CK5: br label %[[DONE]]
+// CK5: [[DONE]]
+// CK5: ret void
+
+#endif // CK5
+
 #endif // HEADER

``````````

</details>


https://github.com/llvm/llvm-project/pull/141507
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to