[SeparateConstOffsetFromGEP] Fix bug handling negative offsets
authorTom Stellard <tstellar@redhat.com>
Fri, 5 May 2023 01:45:48 +0000 (18:45 -0700)
committerTom Stellard <tstellar@redhat.com>
Fri, 5 May 2023 01:45:49 +0000 (18:45 -0700)
commit2e3cabe172c6f2eaf1f097ffeff1664b3768223a
tree479aef0facc157a984fc93c981b7938dd8428f00
parentb0fb98227c90adf2536c9ad644a74d5e92961111
[SeparateConstOffsetFromGEP] Fix bug handling negative offsets

Fix bug constants and sub instructions

When finding constants in a chain starting with the RHS operator of
sub instructions, we were negating the constant before zero extending
it, which is incorrect.

Unfortunately, I was unable to find a simple way to implement this
transformation correctly, so for now I just disabled this optimization
for constants that feed into the RHS of a sub.

Resolves #62379

Transformation from alive2.llvm.org:

    define i16 @src(i8 %a, i8 %b, i8 %c) {
    entry:
    %0 = sub nuw nsw i8 %c, %a
    %1 = sub nuw nsw i8 %b, %0
    %2 = zext i8 %1 to i16
    ret i16 %2
    }

    Before/Bad:

    define i16 @tgt(i8 %a, i8 %b, i8 %c) {
    entry:
    %0 = zext i8 %a to i16
    %1 = zext i8 %b to i16
    %c_neg = sub i8 0, %c
    %c_zext = zext i8 %c_neg to i16
    %2 = sub i16 0, %0
    %3 = sub i16 %1, %2
    %4 = add i16 %3, %c_zext
    ret i16 %4
    }

    Correct:

    define i16 @tgt(i8 %a, i8 %b, i8 %c) {
    entry:
    %0 = zext i8 %a to i16
    %1 = zext i8 %b to i16
    %c_zext = zext i8 %c to i16
    %c_neg = sub i16 0, %c_zext
    %2 = sub i16 0, %0
    %3 = sub i16 %1, %2
    %4 = add i16 %3, %c_neg
    ret i16 %4
    }

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149507
llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
llvm/test/Transforms/SeparateConstOffsetFromGEP/pr62379-zeroext-negative.ll [new file with mode: 0644]