LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 44403 - Folding 'gep p, (q - p)' to q should check it is never used for loads & stores
Summary: Folding 'gep p, (q - p)' to q should check it is never used for loads & stores
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Scalar Optimizations (show other bugs)
Version: trunk
Hardware: PC All
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
: 45444 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-12-29 12:16 PST by Juneyoung Lee
Modified: 2021-03-15 08:33 PDT (History)
7 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Juneyoung Lee 2019-12-29 12:16:26 PST
```

$ cat gep.ll 
define i8* @f(i8* %p, i8* %q) {
  %i = ptrtoint i8* %p to i64
  %j = ptrtoint i8* %q to i64
  %diff = sub i64 %j, %i
  %p2 = getelementptr i8, i8* %p, i64 %diff
  ret i8* %p2
}
$ opt -instcombine gep.ll -S -o -
; ModuleID = 'gep.ll'
source_filename = "gep.ll"
define i8* @f(i8* %p, i8* %q) {
  ret i8* %q
}
```

According to the GEP document:
https://llvm.org/docs/GetElementPtr.html#can-i-compute-the-distance-between-two-objects-and-add-that-value-to-one-address-to-compute-the-other-address
Replacing ‘gep p, (q - p)’ with q is invalid when it is used by memory access operations.
InstCombine and InstSimplify both do this.

`llc gep.ll -o -` emits an optimized assembly, so SelDag or MIR seem to already have optimizations for these this pattern if my understanding is correct?
Comment 1 Sanjay Patel 2019-12-31 05:46:14 PST
I'm not familiar with the rules on this, so just adding a few notes and others can decide what to do:

1. The cited LangRef section says: "ptrtoint and inttoptr provide an alternative way to do this which do not have this restriction". It would be helpful to show the exact alternative sequences, so it's clear what is and is not allowed.

2. The transform in question is in InstSimplify and was added here:
https://reviews.llvm.org/rL216586 (recommit)
https://reviews.llvm.org/rL216439 (original commit)
Comment 2 Nuno Lopes 2020-01-01 11:54:41 PST
(In reply to Sanjay Patel from comment #1)
> I'm not familiar with the rules on this, so just adding a few notes and
> others can decide what to do:
> 
> 1. The cited LangRef section says: "ptrtoint and inttoptr provide an
> alternative way to do this which do not have this restriction". It would be
> helpful to show the exact alternative sequences, so it's clear what is and
> is not allowed.

inttoptr disables a lot of optimizations in LLVM, because LLVM is quite conservative with this. So I would avoid those here.


> 2. The transform in question is in InstSimplify and was added here:
> https://reviews.llvm.org/rL216586 (recommit)
> https://reviews.llvm.org/rL216439 (original commit)

Thanks for the pointers!
This transformation is not correct at the IR level. Only at later levels close to assembly, as in IR there's this notion of memory objects and pointers track from where they were derived from. Only when we get to assembly (not sure about SDAG), it becomes bytes only.

The solution seems to be to leave those GEPs/ptrtoint alone in the IR, and do this optimization at a later step. I don't know if SDAG already has an assembly-like memory model or if it's still higher-level like LLVM IR.
Comment 3 Nuno Lopes 2020-04-06 08:30:42 PDT
*** Bug 45444 has been marked as a duplicate of this bug. ***
Comment 4 Nuno Lopes 2021-03-15 08:31:20 PDT
Fixed by https://reviews.llvm.org/D98588
Comment 5 simonas+llvm.org 2021-03-15 08:33:41 PDT
There's a patch for the same issue in InstSimplify at https://reviews.llvm.org/D98611 as well.