Skip to content

[Analysis] Bail out for negative offsets in isDereferenceableAndAlignedInLoop #99490

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

Merged
merged 2 commits into from
Jul 22, 2024

Conversation

david-arm
Copy link
Contributor

This patch is effectively NFC because it doesn't actually affect any existing tests. It's not possible to even write a test for it, because by accident negative offsets are caught by a subsequent unsigned add overflow check. However, I think it's better to bail out explicitly for negative offsets so that it's more consistent with the unsigned remainder and add calculations.

@llvmbot
Copy link
Member

llvmbot commented Jul 18, 2024

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: David Sherwood (david-arm)

Changes

This patch is effectively NFC because it doesn't actually affect any existing tests. It's not possible to even write a test for it, because by accident negative offsets are caught by a subsequent unsigned add overflow check. However, I think it's better to bail out explicitly for negative offsets so that it's more consistent with the unsigned remainder and add calculations.


Full diff: https://github.com/llvm/llvm-project/pull/99490.diff

1 Files Affected:

  • (modified) llvm/lib/Analysis/Loads.cpp (+7)
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index 1d54a66705a2a..c19a276464e1e 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -313,6 +313,13 @@ bool llvm::isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L,
     const auto *Offset = dyn_cast<SCEVConstant>(StartS->getOperand(0));
     const auto *NewBase = dyn_cast<SCEVUnknown>(StartS->getOperand(1));
     if (StartS->getNumOperands() == 2 && Offset && NewBase) {
+      // The following code below assumes the offset is unsigned, but GEP
+      // offsets are treated as signed so we can end up with a signed value
+      // here too. For example, suppose the initial PHI value is (i8 255),
+      // the offset will be treated as (i8 -1) and sign-extended to (i64 -1).
+      if (Offset->getAPInt().isNegative())
+        return false;
+
       // For the moment, restrict ourselves to the case where the offset is a
       // multiple of the requested alignment and the base is aligned.
       // TODO: generalize if a case found which warrants

@fhahn
Copy link
Contributor

fhahn commented Jul 18, 2024

Thanks for splitting this off!

I think https://llvm.godbolt.org/z/boYbjenvq may serve as a test case; it is using a pointer width of 16 (via the data layout and an alloca that's spanning more than half the available address space) and the GEP computing the address for the conditional load must wrap I think, which would make the inbounds GEP poison, so we shouldn't execute this unconditionally.

…edInLoop

This patch is effectively NFC because it doesn't actually affect
any existing tests. It's not possible to even write a test for it,
because by accident negative offsets are caught by a subsequent
unsigned add overflow check. However, I think it's better to bail
out explicitly for negative offsets so that it's more consistent
with the unsigned remainder and add calculations.
@david-arm
Copy link
Contributor Author

Thanks for splitting this off!

I think https://llvm.godbolt.org/z/boYbjenvq may serve as a test case; it is using a pointer width of 16 (via the data layout and an alloca that's spanning more than half the available address space) and the GEP computing the address for the conditional load must wrap I think, which would make the inbounds GEP poison, so we shouldn't execute this unconditionally.

Thanks a lot for this @fhahn! Your test has actually exposed a genuine bug that's now fixed by this patch. We were treating loads with negative offsets from allocas as being dereferenceable.

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@david-arm david-arm merged commit 102d168 into llvm:main Jul 22, 2024
8 checks passed
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
…edInLoop (#99490)

Summary:
This patch now bails out explicitly for negative offsets so that it's
more consistent with the unsigned remainder and add calculations,
and it fixes a genuine bug as shown with the new test.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251357
@david-arm david-arm deleted the deref_neg_off branch October 3, 2024 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants