Skip to content

Missed optimization: umax(1 << x, 1 << y) => 1 << umax(x, y) #129947

@Kmeakin

Description

@Kmeakin

C code

https://godbolt.org/z/YnEj5KGrW

#include <stdint.h>

uint32_t src1(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (shl_x > shl_y) ? shl_x : shl_y;
}

uint32_t tgt1(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (x > y) ? shl_x : shl_y;
}

uint32_t src2(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (shl_x < shl_y) ? shl_x : shl_y;
}

uint32_t tgt2(uint32_t x, uint32_t y) {
    uint32_t shl_x = 1 << x;
    uint32_t shl_y = 1 << y;
    return (x < y) ? shl_x : shl_y;
}

Alive proof

https://alive2.llvm.org/ce/z/bv698b

----------------------------------------
define i32 @src1(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = shl nuw i32 1, noundef %#0
  %#4 = shl nuw i32 1, noundef %#1
  %#5 = umax i32 %#3, %#4
  %#range_0_%#5 = !range i32 %#5, i32 1, i32 2147483649
  ret i32 %#range_0_%#5
}
=>
define i32 @tgt1(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = umax i32 noundef %#0, noundef %#1
  %#4 = shl nuw i32 1, %#3
  %#range_0_%#4 = !range i32 %#4, i32 1, i32 2147483649
  ret i32 %#range_0_%#4
}
Transformation seems to be correct!


----------------------------------------
define i32 @src2(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = shl nuw i32 1, noundef %#0
  %#4 = shl nuw i32 1, noundef %#1
  %#5 = umin i32 %#3, %#4
  %#range_0_%#5 = !range i32 %#5, i32 1, i32 2147483649
  ret i32 %#range_0_%#5
}
=>
define i32 @tgt2(i32 noundef %#0, i32 noundef %#1) nofree willreturn memory(none) {
#2:
  %#3 = umin i32 noundef %#0, noundef %#1
  %#4 = shl nuw i32 1, %#3
  %#range_0_%#4 = !range i32 %#4, i32 1, i32 2147483649
  ret i32 %#range_0_%#4
}
Transformation seems to be correct!

Summary:
  2 correct transformations
  0 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors

AArch64 assembly

src1:
        mov     w8, #1
        lsl     w9, w8, w0
        lsl     w8, w8, w1
        cmp     w9, w8
        csel    w0, w9, w8, hi
        ret

tgt1:
        cmp     w0, w1
        mov     w8, #1
        csel    w9, w0, w1, hi
        lsl     w0, w8, w9
        ret

src2:
        mov     w8, #1
        lsl     w9, w8, w0
        lsl     w8, w8, w1
        cmp     w9, w8
        csel    w0, w9, w8, lo
        ret

tgt2:
        cmp     w0, w1
        mov     w8, #1
        csel    w9, w0, w1, lo
        lsl     w0, w8, w9
        ret

Metadata

Metadata

Assignees

Labels

good first issuehttps://github.com/llvm/llvm-project/contributellvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesmissed-optimization

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions