Skip to content

Trying to fix undefined symbol error caused by iterator variable #141507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ShashwathiNavada
Copy link
Contributor

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. clang:openmp OpenMP related changes to Clang labels May 26, 2025
@llvmbot
Copy link
Member

llvmbot commented May 26, 2025

@llvm/pr-subscribers-flang-openmp

@llvm/pr-subscribers-clang

Author: None (ShashwathiNavada)

Changes

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 --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

@llvmbot
Copy link
Member

llvmbot commented May 26, 2025

@llvm/pr-subscribers-clang-codegen

Author: None (ShashwathiNavada)

Changes

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 --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

Copy link

github-actions bot commented May 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@@ -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()));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the place to set an initializer for a variable.

For most variable definitions, there's a single location where it makes sense to "define" the variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the place to set an initializer for a variable.

For most variable definitions, there's a single location where it makes sense to "define" the variable.

Thank you for the response, I have moved the definition. Does it look good now?

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To expand on what I mean...

For variables which have a strong definition, we usually don't emit them lazily: there's some statement or declaration which is the "definition" point, and we emit the definition as part of visiting that statement or declaration. This ensures consistency: we consistently emit a definition for things that need a definition.

For variables where the definition isn't necessarily needed, we also have a mechanism for lazily defining them; see DeferredDecls.

I don't want to invent a new way of emitting variable definitions specifically for OpenMP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category flang:openmp
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants