-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CIR] Upstream zero init for global variables #133100
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
[CIR] Upstream zero init for global variables #133100
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesThis change adds zero initialization for global variables Full diff: https://github.com/llvm/llvm-project/pull/133100.diff 7 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ac7658276ec37..eb07acb16ed50 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -67,6 +67,40 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return create<cir::ConstantOp>(loc, attr.getType(), attr);
}
+ mlir::TypedAttr getConstNullPtrAttr(mlir::Type t) {
+ assert(mlir::isa<cir::PointerType>(t) && "expected cir.ptr");
+ return getConstPtrAttr(t, 0);
+ }
+
+ mlir::TypedAttr getZeroAttr(mlir::Type t) {
+ return cir::ZeroAttr::get(getContext(), t);
+ }
+
+ mlir::TypedAttr getZeroInitAttr(mlir::Type ty) {
+ if (mlir::isa<cir::IntType>(ty))
+ return cir::IntAttr::get(ty, 0);
+ if (auto fltType = mlir::dyn_cast<cir::SingleType>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::DoubleType>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::LongDoubleType>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::FP16Type>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::FP128Type>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto fltType = mlir::dyn_cast<cir::BF16Type>(ty))
+ return cir::FPAttr::getZero(fltType);
+ if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
+ return getZeroAttr(arrTy);
+ if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
+ return getConstNullPtrAttr(ptrTy);
+ if (mlir::isa<cir::BoolType>(ty)) {
+ return getCIRBoolAttr(false);
+ }
+ llvm_unreachable("Zero initializer for given type is NYI");
+ }
+
cir::ConstantOp getBool(bool state, mlir::Location loc) {
return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 9776a4e09f9e0..2a37d6c7d1888 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -140,17 +140,20 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
// certain constant expressions is implemented for now.
const VarDecl *initDecl;
const Expr *initExpr = vd->getAnyInitializer(initDecl);
+ mlir::Attribute initializer;
if (initExpr) {
- mlir::Attribute initializer;
if (APValue *value = initDecl->evaluateValue()) {
ConstantEmitter emitter(*this);
initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
} else {
errorNYI(initExpr->getSourceRange(), "non-constant initializer");
}
- varOp.setInitialValueAttr(initializer);
+ } else {
+ initializer = builder.getZeroInitAttr(convertType(astTy));
}
+ varOp.setInitialValueAttr(initializer);
+
// Set CIR's linkage type as appropriate.
cir::GlobalLinkageKind linkage =
getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index a59880352e050..1e74275eab058 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -1,16 +1,16 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
int a[10];
-// CHECK: cir.global external @a : !cir.array<!s32i x 10>
+// CHECK: cir.global external @a = #cir.zero : !cir.array<!s32i x 10>
int aa[10][5];
-// CHECK: cir.global external @aa : !cir.array<!cir.array<!s32i x 5> x 10>
+// CHECK: cir.global external @aa = #cir.zero : !cir.array<!cir.array<!s32i x 5> x 10>
extern int b[10];
-// CHECK: cir.global external @b : !cir.array<!s32i x 10>
+// CHECK: cir.global external @b = #cir.zero : !cir.array<!s32i x 10>
extern int bb[10][5];
-// CHECK: cir.global external @bb : !cir.array<!cir.array<!s32i x 5> x 10>
+// CHECK: cir.global external @bb = #cir.zero : !cir.array<!cir.array<!s32i x 5> x 10>
int c[10] = {};
// CHECK: cir.global external @c = #cir.zero : !cir.array<!s32i x 10>
diff --git a/clang/test/CIR/Lowering/array.cpp b/clang/test/CIR/Lowering/array.cpp
index 763980b9124a3..4fb996aefe79e 100644
--- a/clang/test/CIR/Lowering/array.cpp
+++ b/clang/test/CIR/Lowering/array.cpp
@@ -1,16 +1,16 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - 2>&1 | FileCheck %s
int a[10];
-// CHECK: @a = external dso_local global [10 x i32]
+// CHECK: @a = dso_local global [10 x i32] zeroinitializer
int aa[10][5];
-// CHECK: @aa = external dso_local global [10 x [5 x i32]]
+// CHECK: @aa = dso_local global [10 x [5 x i32]] zeroinitializer
extern int b[10];
-// CHECK: @b = external dso_local global [10 x i32]
+// CHECK: @b = dso_local global [10 x i32] zeroinitializer
extern int bb[10][5];
-// CHECK: @bb = external dso_local global [10 x [5 x i32]]
+// CHECK: @bb = dso_local global [10 x [5 x i32]] zeroinitializer
int c[10] = {};
// CHECK: @c = dso_local global [10 x i32] zeroinitializer
diff --git a/clang/test/CIR/Lowering/global-var-simple.cpp b/clang/test/CIR/Lowering/global-var-simple.cpp
index ab8c6660a311b..33b418430d478 100644
--- a/clang/test/CIR/Lowering/global-var-simple.cpp
+++ b/clang/test/CIR/Lowering/global-var-simple.cpp
@@ -1,21 +1,19 @@
// Global variables of intergal types
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
-// Note: Currently unsupported features include default zero-initialization
-// and alignment. The fact that "external" is only printed for globals
-// without an initializer is a quirk of the LLVM AsmWriter.
+// Note: Currently unsupported features include alignment..
char c;
-// CHECK: @c = external dso_local global i8
+// CHECK: @c = dso_local global i8 0
signed char sc;
-// CHECK: @sc = external dso_local global i8
+// CHECK: @sc = dso_local global i8 0
unsigned char uc;
-// CHECK: @uc = external dso_local global i8
+// CHECK: @uc = dso_local global i8 0
short ss;
-// CHECK: @ss = external dso_local global i16
+// CHECK: @ss = dso_local global i16 0
unsigned short us = 100;
// CHECK: @us = dso_local global i16 100
@@ -24,82 +22,82 @@ int si = 42;
// CHECK: @si = dso_local global i32 42
unsigned ui;
-// CHECK: @ui = external dso_local global i32
+// CHECK: @ui = dso_local global i32 0
long sl;
-// CHECK: @sl = external dso_local global i64
+// CHECK: @sl = dso_local global i64 0
unsigned long ul;
-// CHECK: @ul = external dso_local global i64
+// CHECK: @ul = dso_local global i64 0
long long sll;
-// CHECK: @sll = external dso_local global i64
+// CHECK: @sll = dso_local global i64 0
unsigned long long ull = 123456;
// CHECK: @ull = dso_local global i64 123456
__int128 s128;
-// CHECK: @s128 = external dso_local global i128
+// CHECK: @s128 = dso_local global i128 0
unsigned __int128 u128;
-// CHECK: @u128 = external dso_local global i128
+// CHECK: @u128 = dso_local global i128 0
wchar_t wc;
-// CHECK: @wc = external dso_local global i32
+// CHECK: @wc = dso_local global i32 0
char8_t c8;
-// CHECK: @c8 = external dso_local global i8
+// CHECK: @c8 = dso_local global i8 0
char16_t c16;
-// CHECK: @c16 = external dso_local global i16
+// CHECK: @c16 = dso_local global i16 0
char32_t c32;
-// CHECK: @c32 = external dso_local global i32
+// CHECK: @c32 = dso_local global i32 0
_BitInt(20) sb20;
-// CHECK: @sb20 = external dso_local global i20
+// CHECK: @sb20 = dso_local global i20 0
unsigned _BitInt(48) ub48;
-// CHECK: @ub48 = external dso_local global i48
+// CHECK: @ub48 = dso_local global i48 0
bool boolfalse = false;
// CHECK: @boolfalse = dso_local global i8 0
_Float16 f16;
-// CHECK: @f16 = external dso_local global half
+// CHECK: @f16 = dso_local global half
__bf16 bf16;
-// CHECK: @bf16 = external dso_local global bfloat
+// CHECK: @bf16 = dso_local global bfloat
float f;
-// CHECK: @f = external dso_local global float
+// CHECK: @f = dso_local global float 0.000000e+00
double d = 1.25;
// CHECK: @d = dso_local global double 1.250000e+00
long double ld;
-// CHECK: @ld = external dso_local global x86_fp80
+// CHECK: @ld = dso_local global x86_fp80 0xK00
__float128 f128;
-// CHECK: @f128 = external dso_local global fp128
+// CHECK: @f128 = dso_local global fp128 0xL00
void *vp;
-// CHECK: @vp = external dso_local global ptr{{$}}
+// CHECK: @vp = dso_local global ptr null
int *ip = 0;
// CHECK: @ip = dso_local global ptr null
double *dp;
-// CHECK: @dp = external dso_local global ptr{{$}}
+// CHECK: @dp = dso_local global ptr null
char **cpp;
-// CHECK: @cpp = external dso_local global ptr{{$}}
+// CHECK: @cpp = dso_local global ptr null
void (*fp)();
-// CHECK: @fp = external dso_local global ptr{{$}}
+// CHECK: @fp = dso_local global ptr null
int (*fpii)(int) = 0;
// CHECK: @fpii = dso_local global ptr null
void (*fpvar)(int, ...);
-// CHECK: @fpvar = external dso_local global ptr{{$}}
+// CHECK: @fpvar = dso_local global ptr null
diff --git a/clang/test/CIR/Lowering/hello.c b/clang/test/CIR/Lowering/hello.c
index ff78b6e6f6a5e..f45beafdcb533 100644
--- a/clang/test/CIR/Lowering/hello.c
+++ b/clang/test/CIR/Lowering/hello.c
@@ -3,7 +3,7 @@
int a;
-// CHECK: @a = external dso_local global i32
+// CHECK: @a = dso_local global i32 0
int b = 2;
diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp
index 020ef5f09c650..9a52925303504 100644
--- a/clang/test/CIR/global-var-simple.cpp
+++ b/clang/test/CIR/global-var-simple.cpp
@@ -2,16 +2,16 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s
char c;
-// CHECK: cir.global external @c : !s8i
+// CHECK: cir.global external @c = #cir.int<0> : !s8i
signed char sc;
-// CHECK: cir.global external @sc : !s8i
+// CHECK: cir.global external @sc = #cir.int<0> : !s8i
unsigned char uc;
-// CHECK: cir.global external @uc : !u8i
+// CHECK: cir.global external @uc = #cir.int<0> : !u8i
short ss;
-// CHECK: cir.global external @ss : !s16i
+// CHECK: cir.global external @ss = #cir.int<0> : !s16i
unsigned short us = 100;
// CHECK: cir.global external @us = #cir.int<100> : !u16i
@@ -20,82 +20,82 @@ int si = 42;
// CHECK: cir.global external @si = #cir.int<42> : !s32i
unsigned ui;
-// CHECK: cir.global external @ui : !u32i
+// CHECK: cir.global external @ui = #cir.int<0> : !u32i
long sl;
-// CHECK: cir.global external @sl : !s64i
+// CHECK: cir.global external @sl = #cir.int<0> : !s64i
unsigned long ul;
-// CHECK: cir.global external @ul : !u64i
+// CHECK: cir.global external @ul = #cir.int<0> : !u64i
long long sll;
-// CHECK: cir.global external @sll : !s64i
+// CHECK: cir.global external @sll = #cir.int<0> : !s64i
unsigned long long ull = 123456;
// CHECK: cir.global external @ull = #cir.int<123456> : !u64i
__int128 s128;
-// CHECK: cir.global external @s128 : !s128i
+// CHECK: cir.global external @s128 = #cir.int<0> : !s128i
unsigned __int128 u128;
-// CHECK: cir.global external @u128 : !u128i
+// CHECK: cir.global external @u128 = #cir.int<0> : !u128i
wchar_t wc;
-// CHECK: cir.global external @wc : !s32i
+// CHECK: cir.global external @wc = #cir.int<0> : !s32i
char8_t c8;
-// CHECK: cir.global external @c8 : !u8i
+// CHECK: cir.global external @c8 = #cir.int<0> : !u8i
char16_t c16;
-// CHECK: cir.global external @c16 : !u16i
+// CHECK: cir.global external @c16 = #cir.int<0> : !u16i
char32_t c32;
-// CHECK: cir.global external @c32 : !u32i
+// CHECK: cir.global external @c32 = #cir.int<0> : !u32i
_BitInt(20) sb20;
-// CHECK: cir.global external @sb20 : !cir.int<s, 20>
+// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20>
unsigned _BitInt(48) ub48;
-// CHECK: cir.global external @ub48 : !cir.int<u, 48>
+// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48>
bool boolfalse = false;
// CHECK: cir.global external @boolfalse = #false
_Float16 f16;
-// CHECK: cir.global external @f16 : !cir.f16
+// CHECK: cir.global external @f16 = #cir.fp<0.000000e+00> : !cir.f16
__bf16 bf16;
-// CHECK: cir.global external @bf16 : !cir.bf16
+// CHECK: cir.global external @bf16 = #cir.fp<0.000000e+00> : !cir.bf16
float f;
-// CHECK: cir.global external @f : !cir.float
+// CHECK: cir.global external @f = #cir.fp<0.000000e+00> : !cir.float
double d = 1.25;
// CHECK: cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
long double ld;
-// CHECK: cir.global external @ld : !cir.long_double<!cir.f80>
+// CHECK: cir.global external @ld = #cir.fp<0.000000e+00> : !cir.long_double<!cir.f80>
__float128 f128;
-// CHECK: cir.global external @f128 : !cir.f128
+// CHECK: cir.global external @f128 = #cir.fp<0.000000e+00> : !cir.f128
void *vp;
-// CHECK: cir.global external @vp : !cir.ptr<!void>
+// CHECK: cir.global external @vp = #cir.ptr<null> : !cir.ptr<!void>
int *ip = 0;
// CHECK: cir.global external @ip = #cir.ptr<null> : !cir.ptr<!s32i>
double *dp;
-// CHECK: cir.global external @dp : !cir.ptr<!cir.double>
+// CHECK: cir.global external @dp = #cir.ptr<null> : !cir.ptr<!cir.double>
char **cpp;
-// CHECK: cir.global external @cpp : !cir.ptr<!cir.ptr<!s8i>>
+// CHECK: cir.global external @cpp = #cir.ptr<null> : !cir.ptr<!cir.ptr<!s8i>>
void (*fp)();
-// CHECK: cir.global external @fp : !cir.ptr<!cir.func<()>>
+// CHECK: cir.global external @fp = #cir.ptr<null> : !cir.ptr<!cir.func<()>>
int (*fpii)(int) = 0;
// CHECK: cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i) -> !s32i>>
void (*fpvar)(int, ...);
-// CHECK: cir.global external @fpvar : !cir.ptr<!cir.func<(!s32i, ...)>>
+// CHECK: cir.global external @fpvar = #cir.ptr<null> : !cir.ptr<!cir.func<(!s32i, ...)>>
|
999b8e4
to
b4aafe8
Compare
return cir::ZeroAttr::get(getContext(), t); | ||
} | ||
|
||
mlir::TypedAttr getZeroInitAttr(mlir::Type ty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to update this function in the incubator to add the missing types @andykaylor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks fine!
mlir::TypedAttr getZeroInitAttr(mlir::Type ty) { | ||
if (mlir::isa<cir::IntType>(ty)) | ||
return cir::IntAttr::get(ty, 0); | ||
if (auto fltType = mlir::dyn_cast<cir::SingleType>(ty)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will work:
if (cir::isAnyFloatingPointType(ty))
return cir::FPAttr::getZero(ty);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Update getZeroInitAttr to cover more FP types, Backport from (llvm/llvm-project#133100)
This change adds zero initialization for global variables