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 50208 - InstSimplify: incorrect fold of pointer comparison between globals
Summary: InstSimplify: incorrect fold of pointer comparison between globals
Status: NEW
Alias: None
Product: libraries
Classification: Unclassified
Component: Scalar Optimizations (show other bugs)
Version: trunk
Hardware: All All
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords: miscompilation
Depends on:
Blocks:
 
Reported: 2021-05-03 10:41 PDT by Nuno Lopes
Modified: 2021-05-09 05:18 PDT (History)
5 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 Nuno Lopes 2021-05-03 10:41:55 PDT
test: Transforms/InstSimplify/ConstProp/icmp-null.ll
The transformation below is only correct if the gep is over i8*, and not with non-byte-sized types. This is correct: https://alive2.llvm.org/ce/z/S_TsHW

----------------------------------------
@g2 = global 4 bytes, align 4
@g = global 8 bytes, align 4

define i1 @null_gep_ne_global() {
  %__constexpr_0 = ptrtoint * @g2 to i64
  %gep = gep * null, 8 x i64 %__constexpr_0  ; <-- notice the 8 x
  %cmp = icmp ne * %gep, @g
  ret i1 %cmp
}
=>
@g2 = global 4 bytes, align 4
@g = global 8 bytes, align 4

define i1 @null_gep_ne_global() {
  ret i1 1
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:

Source:
i64 %__constexpr_0 = #x924925b6db6f5564 (10540997870133138788, -7905746203576412828)
* %gep = pointer(non-local, block_id=0, offset=-7905737407482647776)
i1 %cmp = #x0 (0)

SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 >       size: 0 align: 1        alloc type: 0   address: 0
Block 1 >       size: 4 align: 4        alloc type: 0   address: 10540997870133138788
Block 2 >       size: 8 align: 4        alloc type: 0   address: 10541006666226903840

Target:
Source value: #x0 (0)
Target value: #x1 (1)
Comment 1 Nikita Popov 2021-05-03 11:11:06 PDT
Relevant code is https://github.com/llvm/llvm-project/blob/1d299252dd52ade0e87485be29443aa69be9e910/llvm/lib/IR/ConstantFold.cpp#L1846-L1853 I think.

The code is also wrong in that !isNullValue doesn't mean that the index can't be zero, just that it's not known to be zero.

Maybe this fold can be dropped entirely? It seems pretty useless to me.
Comment 2 Nuno Lopes 2021-05-09 04:13:07 PDT
Here's another one, which folds (x-1) ugt x -> true:

define i1 @global_gep_ugt_global_neg_offset() {
  %gep = gep * @g, 8 x i64 -1
  %cmp = icmp ugt * %gep, @g
  ret i1 %cmp
}
=>
define i1 @global_gep_ugt_global_neg_offset() {
  ret i1 1
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:

Source:
* %gep = pointer(non-local, block_id=0, offset=-8)
i1 %cmp = #x0 (0)

Target:
Source value: #x0 (0)
Target value: #x1 (1)
Comment 3 Nikita Popov 2021-05-09 04:25:17 PDT
I believe the right way to fix all these folds is https://reviews.llvm.org/D97665, which limits them to inbounds only. While some of them are also valid without inbounds in limited circumstances, I don't think it's worth bothering with the non-inbounds case here.
Comment 4 Nuno Lopes 2021-05-09 05:18:15 PDT
(In reply to Nikita Popov from comment #3)
> I believe the right way to fix all these folds is
> https://reviews.llvm.org/D97665, which limits them to inbounds only. While
> some of them are also valid without inbounds in limited circumstances, I
> don't think it's worth bothering with the non-inbounds case here.

I agree; it's not worth it to spend a lot of time with non-inbounds geps. Plus these folds probably don't kick in that often.

But, the last transformation I pasted is completely wrong (likely a copy-paste mistake), as it's trying to prove that (x-1) > x. Since x is non-null, that isn't possible.