declare void @use(...) nofree memory(read)
@use = constant ? bytes, exec, align 8
define ptr @f5(ptr %p, i1 %cond) {
#0:
br i1 %cond, label %bb1, label %bb2
bb2:
%v2 = load ptr, ptr %p, align 8
call void @use(...ptr %v2) nofree memory(read)
br label %merge
bb1:
%v1 = load i64, ptr %p, align 4
call void @use(...i64 %v1) nofree memory(read)
br label %merge
merge:
%v3 = load i64, ptr %p, align 4
call void @use(...i64 %v3) nofree memory(read)
%v4 = load ptr, ptr %p, align 8
ret ptr %v4
}
=>
declare void @use(...) nofree memory(read)
@use = constant ? bytes, exec, align 8
define ptr @f5(ptr %p, i1 %cond) {
#0:
br i1 %cond, label %bb1, label %bb2
bb2:
%v2 = load ptr, ptr %p, align 8
call void @use(...ptr %v2) nofree memory(read)
br label %merge
bb1:
%v1 = load i64, ptr %p, align 4
call void @use(...i64 %v1) nofree memory(read)
br label %merge
merge:
%v3 = load i64, ptr %p, align 4
call void @use(...i64 %v3) nofree memory(read)
%v4.cast = int2ptr i64 %v3 to ptr
ret ptr %v4.cast
}
Transformation doesn't verify!
ERROR: Target is more poisonous than source
Example:
ptr %p = pointer(non-local, block_id=1, offset=0) / Address=#x0000000000000008
i1 %cond = #x1 (1)
Source:
>> Jump to %bb1
i64 %v1 = poison
Function returned
>> Jump to %merge
i64 %v3 = poison
Function returned
ptr %v4 = pointer(non-local, block_id=4, offset=0) / Address=#x0000000000000001
SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 > size: 0 align: 4 alloc type: 0 alive: false address: 0
Block 1 > size: 11 align: 8 alloc type: 0 alive: true address: 8 const
Contents:
1: pointer(non-local, block_id=4, offset=0), byte offset=1
*: pointer(non-local, block_id=4, offset=0), byte offset=0
Block 2 > size: 0 align: 8 alloc type: 0 alive: true address: 8
Contents:
1: pointer(non-local, block_id=4, offset=0), byte offset=1
*: pointer(non-local, block_id=4, offset=0), byte offset=0
Block 3 > size: 0 align: 8 alloc type: 0 alive: true address: 8
Contents:
1: pointer(non-local, block_id=4, offset=0), byte offset=1
*: pointer(non-local, block_id=4, offset=0), byte offset=0
Block 4 > size: 0 align: 1 alloc type: 0 alive: true address: 1
Contents:
1: pointer(non-local, block_id=4, offset=0), byte offset=1
*: pointer(non-local, block_id=4, offset=0), byte offset=0
Block 5 > size: 0 align: 8 alloc type: 0 alive: true address: 8
Contents:
1: pointer(non-local, block_id=4, offset=0), byte offset=1
*: pointer(non-local, block_id=4, offset=0), byte offset=0
Block 6 > size: 0 align: 2 alloc type: 0 alive: true address: 2
Contents:
1: pointer(non-local, block_id=4, offset=0), byte offset=1
*: pointer(non-local, block_id=4, offset=0), byte offset=0
Target:
>> Jump to %bb1
i64 %v1 = poison
Function returned
>> Jump to %merge
i64 %v3 = poison
Function returned
ptr %v4.cast = poison
Source value: pointer(non-local, block_id=4, offset=0) / Address=#x0000000000000001
Target value: poison
If a pointer is stored in memory,
%v3returnspoison, while%v4returns the pointer value in the original program.Introducing the cast in the target program is unsound as
%v3ispoisonand%v4becomespoison.Alive2: https://alive2.llvm.org/ce/z/FW5zqi