I agree that null_pointer_is_valid should be a module flag rather than a function attribute. “Can an allocated object exist at address 0?” is not a property of an individual function. And in particular the question “Can a global variable have address 0?” needs a module-level rather than function-level answer, as it is a module-level entity.
Having a module flag for this is still compatible with LTO – we just need to define the appropriate merging behavior (which is “if any module has null_pointer_is_valid, the result module also has null_pointer_is_valid”).
Looking back at RFC: Implementing -fno-delete-null-pointer-checks in clang, it seems like the suggestion to use a function attribute instead of a module flag came from @efriedma-quic, maybe they have some more insight into this choice?