This is an archive of the discontinued LLVM Phabricator instance.

[flang]Zero Initialize simple types
ClosedPublic

Authored by Leporacanthicus on May 4 2023, 11:06 AM.

Details

Summary

Instead of filling uninitialized global variables with "undef",
initialize them with 0. Only for Integer, Float or Logical type
variables. Complex, user defined data structures, arrays, etc
are not supported at this point.

This patch fixes the main problem of
https://github.com/llvm/llvm-project/issues/62432

Diff Detail

Event Timeline

Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptMay 4 2023, 11:06 AM
Leporacanthicus requested review of this revision.May 4 2023, 11:06 AM

Thanks for working on this!

Note that there is a fir::ZeroOp that is intended to create some zero initialized data regardless of the type, but it currently is a TODO in codegen for aggregate/array types (That is actually the fir.zero_init). I think a zeroinitialzer operation may be required in LLVM MLIR dialect (like for the poison/undef op), so that we can propagate fir::ZeroOp into an LLVM zeroinitializer.

Thanks for working on this!

Note that there is a fir::ZeroOp that is intended to create some zero initialized data regardless of the type, but it currently is a TODO in codegen for aggregate/array types (That is actually the fir.zero_init). I think a zeroinitialzer operation may be required in LLVM MLIR dialect (like for the poison/undef op), so that we can propagate fir::ZeroOp into an LLVM zeroinitializer.

Yes, the "createNullConstant" creates a fir::ZeroOp, this is why I also had to make a minor change to the code dealing with that operation (because we want to retain the original logical, rather than use integer when the original type is a logical. Could probably do with a synonym or rename, but it does produce the correct operation. [I think LLVM has a similar function, and it's used to create all sorts of zero-filled types, if I recall correctly]. I guess we could just create the ZeroOp directly, rather than calling a function - I'll fix that now.

It would indeed be great to have a zeroinitializer that goes all the way through MLIR. There is a thread on that in Discourse:
https://discourse.llvm.org/t/zero-initialization-for-globals-with-common-linkage/1762
As far as I can tell, nobody has implemented this. I have made a comment, and I will see if I can do that - I don't know if it's much work.

Filling something with zeros does make it a LLVM zeroinitializer attribute. So for example, if I do complex c = (0, 0) that becomes c = global {float, float} zeroinitializer in LLVM-IR, even tho' it's a whole bunch of operations in FIR.

One of the reasons I stuck to "only basic types" is that the code is incomplete for other types. If we had a mlir::LLVM::ZeroOp (or whatever the name should be), then that could be directly translated to LLVM zeroinitializer too.

Thanks for working on this!

Note that there is a fir::ZeroOp that is intended to create some zero initialized data regardless of the type, but it currently is a TODO in codegen for aggregate/array types (That is actually the fir.zero_init). I think a zeroinitialzer operation may be required in LLVM MLIR dialect (like for the poison/undef op), so that we can propagate fir::ZeroOp into an LLVM zeroinitializer.

Yes, the "createNullConstant" creates a fir::ZeroOp, this is why I also had to make a minor change to the code dealing with that operation (because we want to retain the original logical, rather than use integer when the original type is a logical. Could probably do with a synonym or rename, but it does produce the correct operation. [I think LLVM has a similar function, and it's used to create all sorts of zero-filled types, if I recall correctly]. I guess we could just create the ZeroOp directly, rather than calling a function - I'll fix that now.

It would indeed be great to have a zeroinitializer that goes all the way through MLIR. There is a thread on that in Discourse:
https://discourse.llvm.org/t/zero-initialization-for-globals-with-common-linkage/1762
As far as I can tell, nobody has implemented this. I have made a comment, and I will see if I can do that - I don't know if it's much work.

Filling something with zeros does make it a LLVM zeroinitializer attribute. So for example, if I do complex c = (0, 0) that becomes c = global {float, float} zeroinitializer in LLVM-IR, even tho' it's a whole bunch of operations in FIR.

One of the reasons I stuck to "only basic types" is that the code is incomplete for other types. If we had a mlir::LLVM::ZeroOp (or whatever the name should be), then that could be directly translated to LLVM zeroinitializer too.

It would be really great to get "all zero" all the way from FIR to LLVM's zero_initializer for any sort of type. Semi-related is the quadratic behavior of converting large blobs (e.g., an array of a few million tuples of type {f64, f32, i64, i8*}) of data to LLVM via the LLVM-IR dialect conversion. Various mitigations have been tried, but it's still an area that needs some attention on the MLIR side as well.

Just create a ZeroOp instead of calling createNullConstant.

jeanPerier accepted this revision.May 5 2023, 8:30 AM

Thanks, this is an improvement on the current situation (and thanks for the link to the thread).
Can you add a quick line in flang/docs/Extensions.md under "Extensions, deletions, and legacy features supported by default" that saved integer, logical, and real scalars are zero initialized?

I think we could use mlir attributes to support zero initialization of all intrinsic types/intrinsic arrays too (but that can be done independently).

Derived type can wait for zeroinitializer, the reliance on them being zero initialized is probably less common and the codegen implementation would be cumbersome/yields big compile time for derived type arrays due to the poor llvm.insert folding performance.

This revision is now accepted and ready to land.May 5 2023, 8:30 AM

Update docs to let people know we changed to zero initialize some
globals.

This revision was automatically updated to reflect the committed changes.