Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[InstCombine] Unfortunate assume condition optimization #158324

@nikic

Description

@nikic

https://llvm.godbolt.org/z/qoMYnaY35

target datalayout = "n8:16:32:64"

define i32 @test(ptr %p) {
  %pi = ptrtoint ptr %p to i64
  %pi.shr = lshr i64 %pi, 32
  %pi.hi = trunc nuw i64 %pi.shr to i32
  %umin = call i32 @llvm.umin.i32(i32 %pi.hi, i32 41)
  %cmp = icmp ne i32 %umin, 41
  call void @llvm.assume(i1 %cmp)
  ret i32 %umin
}

define i32 @test2(i32 %arg) {
  %umin = call i32 @llvm.umin.i32(i32 %arg, i32 41)
  %cmp = icmp ne i32 %umin, 41
  call void @llvm.assume(i1 %cmp)
  ret i32 %umin
}

With -passes='instcombine<max-iterations=2>':

define i32 @test(ptr %p) {
  %pi = ptrtoint ptr %p to i64
  %pi.shr = lshr i64 %pi, 32
  %pi.hi = trunc nuw i64 %pi.shr to i32
  %umin = call i32 @llvm.umin.i32(i32 %pi.hi, i32 41)
  %cmp = icmp ult ptr %p, inttoptr (i64 176093659136 to ptr)
  call void @llvm.assume(i1 %cmp)
  ret i32 %umin
}

define i32 @test2(i32 %arg) {
  %cmp = icmp ult i32 %arg, 41
  call void @llvm.assume(i1 %cmp)
  ret i32 %arg
}

In the second case the assume is used to eliminate the umin. In the first case (the pattern that actually occurs) we end up simplifying the comparison to work on the original pointer, and at that point aren't able to optimize away the umin anymore.

Not entirely sure what can be done about this. CVP can at least handle the following variant with the assume operating on an integer instead of a pointer:

define i32 @test(i64 %pi) {
  %pi.shr = lshr i64 %pi, 32
  %pi.hi = trunc nuw i64 %pi.shr to i32
  %umin = call i32 @llvm.umin.i32(i32 %pi.hi, i32 41)
  %cmp = icmp ult i64 %pi, 176093659136
  call void @llvm.assume(i1 %cmp)
  ret i32 %umin
}

So supporting tracking the address range for pointers in LVI might be an option.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions