[PATCH] D78430: [InstSimplify] fold and/or of compares with equality to min/max constant
Roman Lebedev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 23 02:06:24 PDT 2020
lebedev.ri accepted this revision.
lebedev.ri added a comment.
This revision is now accepted and ready to land.
This looks good to me, but we have a soundness problem with existing nullptr folds, specifically
`(X == null) || (X u<= Y) --> X u<= Y` and `(X != null) && (X u> Y) --> X u> Y`
================
Comment at: llvm/test/Transforms/InstSimplify/and-or-icmp-nullptr.ll:217-248
define i1 @ule_or_min_commute(i8* %x, i8* %y) {
; CHECK-LABEL: @ule_or_min_commute(
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8* [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%cmp = icmp ule i8* %x, %y
%cmpeq = icmp eq i8* %x, null
----------------
Alive says all these are [preexisting] miscompiles, i think:
```
----------------------------------------
define i1 @ule_or_min(* %x, * %y) {
%0:
%cmp = icmp ule * %x, %y
%cmpeq = icmp eq * %x, null
%r = or i1 %cmp, %cmpeq
ret i1 %r
}
=>
define i1 @ule_or_min(* %x, * %y) {
%0:
%cmp = icmp ule * %x, %y
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=1, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x1 (1)
i1 %r = #x1 (1)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 4 alloc type: 0
Target:
i1 %cmp = #x0 (0)
Source value: #x1 (1)
Target value: #x0 (0)
----------------------------------------
define i1 @ule_or_min_commute(* %x, * %y) {
%0:
%cmp = icmp ule * %x, %y
%cmpeq = icmp eq * %x, null
%r = or i1 %cmpeq, %cmp
ret i1 %r
}
=>
define i1 @ule_or_min_commute(* %x, * %y) {
%0:
%cmp = icmp ule * %x, %y
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=2, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x1 (1)
i1 %r = #x1 (1)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 0 alloc type: 0
Target:
i1 %cmp = #x0 (0)
Source value: #x1 (1)
Target value: #x0 (0)
----------------------------------------
define i1 @ule_swap_or_min(* %x, * %y) {
%0:
%cmp = icmp uge * %y, %x
%cmpeq = icmp eq * %x, null
%r = or i1 %cmp, %cmpeq
ret i1 %r
}
=>
define i1 @ule_swap_or_min(* %x, * %y) {
%0:
%cmp = icmp uge * %y, %x
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=2, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x1 (1)
i1 %r = #x1 (1)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 4 alloc type: 0
Block 2 > size: 0 align: 2 alloc type: 0
Target:
i1 %cmp = #x0 (0)
Source value: #x1 (1)
Target value: #x0 (0)
----------------------------------------
define i1 @ule_swap_or_min_commute(* %x, * %y) {
%0:
%cmp = icmp uge * %y, %x
%cmpeq = icmp eq * %x, null
%r = or i1 %cmpeq, %cmp
ret i1 %r
}
=>
define i1 @ule_swap_or_min_commute(* %x, * %y) {
%0:
%cmp = icmp uge * %y, %x
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=1, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x1 (1)
i1 %r = #x1 (1)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 2 alloc type: 0
Target:
i1 %cmp = #x0 (0)
Source value: #x1 (1)
Target value: #x0 (0)
```
================
Comment at: llvm/test/Transforms/InstSimplify/and-or-icmp-nullptr.ll:265-313
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; (X != null) && (X > Y) --> X > Y
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
define i1 @ugt_and_not_min(i8* %x, i8* %y) {
----------------
Likewise:
```
----------------------------------------
define i1 @ugt_and_not_min(* %x, * %y) {
%0:
%cmp = icmp ugt * %x, %y
%cmpeq = icmp ne * %x, null
%r = and i1 %cmp, %cmpeq
ret i1 %r
}
=>
define i1 @ugt_and_not_min(* %x, * %y) {
%0:
%cmp = icmp ugt * %x, %y
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=2, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x0 (0)
i1 %r = #x0 (0)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 2 alloc type: 0
Target:
i1 %cmp = #x1 (1)
Source value: #x0 (0)
Target value: #x1 (1)
----------------------------------------
define i1 @ugt_and_not_min_commute(* %x, * %y) {
%0:
%cmp = icmp ugt * %x, %y
%cmpeq = icmp ne * %x, null
%r = and i1 %cmpeq, %cmp
ret i1 %r
}
=>
define i1 @ugt_and_not_min_commute(* %x, * %y) {
%0:
%cmp = icmp ugt * %x, %y
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=2, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x0 (0)
i1 %r = #x0 (0)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 2 alloc type: 0
Target:
i1 %cmp = #x1 (1)
Source value: #x0 (0)
Target value: #x1 (1)
----------------------------------------
define i1 @ugt_swap_and_not_min(* %x, * %y) {
%0:
%cmp = icmp ult * %y, %x
%cmpeq = icmp ne * %x, null
%r = and i1 %cmp, %cmpeq
ret i1 %r
}
=>
define i1 @ugt_swap_and_not_min(* %x, * %y) {
%0:
%cmp = icmp ult * %y, %x
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=2, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x0 (0)
i1 %r = #x0 (0)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 2 alloc type: 0
Target:
i1 %cmp = #x1 (1)
Source value: #x0 (0)
Target value: #x1 (1)
----------------------------------------
define i1 @ugt_swap_and_not_min_commute(* %x, * %y) {
%0:
%cmp = icmp ult * %y, %x
%cmpeq = icmp ne * %x, null
%r = and i1 %cmpeq, %cmp
ret i1 %r
}
=>
define i1 @ugt_swap_and_not_min_commute(* %x, * %y) {
%0:
%cmp = icmp ult * %y, %x
ret i1 %cmp
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
* %x = null
* %y = pointer(non-local, block_id=1, offset=0)
Source:
i1 %cmp = undef
i1 %cmpeq = #x0 (0)
i1 %r = #x0 (0)
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 64 alloc type: 0
Block 1 > size: 0 align: 2 alloc type: 0
Block 2 > size: 0 align: 4 alloc type: 0
Target:
i1 %cmp = #x1 (1)
Source value: #x0 (0)
Target value: #x1 (1)
```
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D78430/new/
https://reviews.llvm.org/D78430
More information about the llvm-commits
mailing list