This is an archive of the discontinued LLVM Phabricator instance.

[LangRef] Make !range, !nonnull and !align return poison instead of IUB
ClosedPublic

Authored by nikic on Jan 10 2023, 7:15 AM.

Details

Summary

Make violation of !range, !nonnull and !align metadata return poison instead of causing immediate undefined behavior. This makes the behavior match that of the nonnull and align parameter and return value attributes. The previous behavior can be restored by additionally specifying the !noundef metadata, same as with parameters.

Some benefits of this change are:

  • This is needed to fix https://github.com/llvm/llvm-project/issues/59888. Under current semantics, it is illegal to add !range annotations based on known bits. Unless we want to drop that optimization entirely, we need to change the !range semantics.
  • This allows preserving range/nonnull/align metadata on speculated loads. !noundef metadata needs to be dropped, but the poison-generating metadata can be retained.

I don't think there are really disadvantages to the change (apart from the need to review and adjust optimizations for the new semantics), as the old behavior is still available via !noundef, so it should be strictly more flexible.

Diff Detail

Event Timeline

nikic created this revision.Jan 10 2023, 7:15 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 10 2023, 7:15 AM
Herald added a subscriber: StephenFan. · View Herald Transcript
nikic requested review of this revision.Jan 10 2023, 7:15 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 10 2023, 7:15 AM
jdoerfert accepted this revision.Jan 10 2023, 10:14 AM

+1. This is what we have (slowly) been doing elsewhere and it works. Thanks!

This revision is now accepted and ready to land.Jan 10 2023, 10:14 AM
nlopes accepted this revision.Jan 11 2023, 10:11 AM

Sounds good, thanks!
I implemented this in Alive2 and I got zero failures in LLVM's test suite. Either it doesn't have many !ranges or we are good.

This revision was landed with ongoing or failed builds.Jan 12 2023, 1:01 AM
This revision was automatically updated to reflect the committed changes.
nikic added a comment.Jan 12 2023, 5:57 AM

Sounds good, thanks!
I implemented this in Alive2 and I got zero failures in LLVM's test suite. Either it doesn't have many !ranges or we are good.

Shouldn't this test have failed? https://github.com/llvm/llvm-project/blob/main/llvm/test/Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll Or did you only adjust !range but not !nonnull?

Sounds good, thanks!
I implemented this in Alive2 and I got zero failures in LLVM's test suite. Either it doesn't have many !ranges or we are good.

Shouldn't this test have failed? https://github.com/llvm/llvm-project/blob/main/llvm/test/Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll Or did you only adjust !range but not !nonnull?

It seems it's not even implemented 😅:

ERROR: Unsupported metadata: 11
ERROR: Could not translate 'single_store' to Alive IR

Ok, I'll add it to my todo list. maybe over the weekend..

Sounds good, thanks!
I implemented this in Alive2 and I got zero failures in LLVM's test suite. Either it doesn't have many !ranges or we are good.

Shouldn't this test have failed? https://github.com/llvm/llvm-project/blob/main/llvm/test/Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll Or did you only adjust !range but not !nonnull?

It does now:

define ptr @no_store_single_load() {
%entry:
  %buf = alloca i64 8, align 8
  %buf.load = load ptr, ptr %buf, align 8
  %buf.load_2 = !nonnull ptr %buf.load
  ret ptr %buf.load_2
}
=>
define ptr @no_store_single_load() noreturn nonnull nofree noalias willreturn memory(none) {
%entry:
  assume i1 0
}
Transformation doesn't verify!

ERROR: Source is more defined than target

I'll rerun LLVM unit tests again.

Three failures:

  • Transforms/InstCombine/loadstore-metadata.ll
  • Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll
  • Transforms/SROA/preserve-nonnull.ll
nikic added a comment.Jan 20 2023, 7:45 AM

Three failures:

  • Transforms/InstCombine/loadstore-metadata.ll
  • Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll
  • Transforms/SROA/preserve-nonnull.ll

The last two should be fixed by https://github.com/llvm/llvm-project/commit/e6241cbdcbf3cc9beb49460578466e18936ef220.

For the InstCombine test the online alive instance currently crashes (https://alive2.llvm.org/ce/z/dZko2g), so not sure what's wrong with that one.

Three failures:

  • Transforms/InstCombine/loadstore-metadata.ll
  • Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll
  • Transforms/SROA/preserve-nonnull.ll

The last two should be fixed by https://github.com/llvm/llvm-project/commit/e6241cbdcbf3cc9beb49460578466e18936ef220.

Thank you!

For the InstCombine test the online alive instance currently crashes (https://alive2.llvm.org/ce/z/dZko2g), so not sure what's wrong with that one.

It doesn't like this: !nonnull !6.
It is failing the assertion that !nonnull has no arguments. I would hope the IR verifier would catch this though.

nikic added a comment.Jan 23 2023, 2:18 AM

Three failures:

  • Transforms/InstCombine/loadstore-metadata.ll
  • Transforms/Mem2Reg/preserve-nonnull-load-metadata.ll
  • Transforms/SROA/preserve-nonnull.ll

The last two should be fixed by https://github.com/llvm/llvm-project/commit/e6241cbdcbf3cc9beb49460578466e18936ef220.

Thank you!

For the InstCombine test the online alive instance currently crashes (https://alive2.llvm.org/ce/z/dZko2g), so not sure what's wrong with that one.

It doesn't like this: !nonnull !6.
It is failing the assertion that !nonnull has no arguments. I would hope the IR verifier would catch this though.

I've added the verifier check in https://github.com/llvm/llvm-project/commit/474f20ba26400559e5d99fd4f29926253092f00b.