Skip to content

Move icmp ult before mul nuw by a constant #56563

Closed
@scottmcm

Description

@scottmcm

Overview: When the multiplication is nuw and B & C are constants, transform

  • x * B < Ca < ⌈C / B⌉
  • x * B ≤ Ca ≤ ⌊C / B⌋

Validity proof for a specific example, as a demonstration: https://alive2.llvm.org/ce/z/H-W9Zb

define i64 @src(i64 %x) denormal-fp-math=ieee,ieee {
%start:
  %_4.i = zext i64 %x to i128
  %p.i = mul nuw i128 %_4.i, 5
  %_8.i = icmp ult i128 %p.i, 9223372036854775808
  %0 = trunc i128 %p.i to i64
  %.0.i = select i1 %_8.i, i64 %0, i64 -1
  ret i64 %.0.i
}
=>
define i64 @tgt(i64 %x) denormal-fp-math=ieee,ieee {
%start:
  %_4.i = zext i64 %x to i128
  %_8.i = icmp ult i128 %_4.i, 1844674407370955162
  %p.i = mul nuw i128 %_4.i, 5
  %0 = trunc i128 %p.i to i64
  %.0.i = select i1 %_8.i, i64 %0, i64 -1
  ret i64 %.0.i
}
Transformation seems to be correct!

This is particularly worth doing in that example, since other existing transformations can then remove the zext+trunc:

define i64 @tgt(i64 %x) unnamed_addr #0 {
  %_8.i = icmp ult i64 %x, 1844674407370955162
  %p.i = mul i64 %x, 5
  %.0.i = select i1 %_8.i, i64 %p.i, i64 -1
  ret i64 %.0.i
}

And that means much tidier output overall:

src:                                    # @src
        mov     rax, rdi
        mov     ecx, 5
        mul     rcx
        movabs  rcx, -9223372036854775808
        cmp     rax, rcx
        sbb     rdx, 0
        mov     rcx, -1
        cmovae  rax, rcx
        ret
tgt:                                    # @tgt
        movabs  rax, 1844674407370955162
        cmp     rdi, rax
        lea     rcx, [rdi + 4*rdi]
        mov     rax, -1
        cmovb   rax, rcx
        ret

(This is a sibling issue to #56562, which discusses a similar thing for umul.with.overflow)

EDIT: Updated to not have this need to care about the zext -- other existing things will handle that already.

Metadata

Metadata

Assignees

No one assigned

    Labels

    llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions