Skip to content

Collapse icmps due to nuw+noundef #202240

@scottmcm

Description

@scottmcm

Today, the following doesn't optimize further: https://llvm.godbolt.org/z/s4jrdnrcq

define noundef { i16, i1 } @src(i16 noundef %num) unnamed_addr {
start:
  %r = shl nuw i16 %num, 8
  %_3 = icmp ult i16 %num, 256
  %0 = insertvalue { i16, i1 } poison, i16 %r, 0
  %1 = insertvalue { i16, i1 } %0, i1 %_3, 1
  ret { i16, i1 } %1
}

But since shifting the num left by 8 didn't overflow, that means it's definitely below 256, and the icmp is always true: https://alive2.llvm.org/ce/z/qNrDgQ

define {i16, i1, i8} @src(i16 noundef %num) noundef {
start:
  %r = shl nuw i16 noundef %num, 8
  %_3 = icmp ult i16 noundef %num, 256
  %#0 = insertvalue {i16, i1, i8} poison, i16 %r, 0
  %#1 = insertvalue {i16, i1, i8} %#0, i1 %_3, 1
  ret {i16, i1, i8} %#1
}
=>
define {i16, i1, i8} @tgt(i16 noundef %num) noundef {
start:
  %r = shl nuw i16 noundef %num, 8
  %#0 = insertvalue {i16, i1, i8} poison, i16 %r, 0
  %#1 = insertvalue {i16, i1, i8} %#0, i1 1, 1
  ret {i16, i1, i8} %#1
}
Transformation seems to be correct!

Inspired by rust-lang/rust#157560 where I was adding some nuw and was surprised things didn't optimize out.


Note that the noundefs are load-bearing here: nuw is just poison-generating, not UB, so without the noundef on the return then the optimization is not legal (https://alive2.llvm.org/ce/z/K6-NnE) since someone might just never look at the product.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions