Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[InstCombine] likely incorrect optimization of sitofp/fptosi roundtrip #55150

Closed
regehr opened this issue Apr 27, 2022 · 7 comments
Closed

[InstCombine] likely incorrect optimization of sitofp/fptosi roundtrip #55150

regehr opened this issue Apr 27, 2022 · 7 comments

Comments

@regehr
Copy link
Contributor

regehr commented Apr 27, 2022

here's a test case that lives in llvm/test/Transforms/InstCombine/sitofp.ll:

; This can fold because the 54-bit output is signed and we discard the sign bit.

define i54 @test18(i64 %A) {
; CHECK-LABEL: @test18(
; CHECK-NEXT:    [[C:%.*]] = trunc i64 [[A:%.*]] to i54
; CHECK-NEXT:    ret i54 [[C]]
;
  %B = sitofp i64 %A to double
  %C = fptosi double %B to i54
  ret i54 %C
}

it is also performed by the x64 and arm64 backends (https://godbolt.org/z/fT15zMncK). since it is capable of changing the value that is returned, we believe it to be incorrect in the absence of fast math flags.

the alive2 compiler explorer instance times out on it, but this is the output:

regehr@john-home:~$ ~/alive2/build/alive-tv --smt-to=0 foo.ll

----------------------------------------
define i54 @test18(i64 %A) {
%0:
  %B = sitofp i64 %A to double, exceptions=ignore
  %C = fptosi double %B to i54, exceptions=ignore
  ret i54 %C
}
=>
define i54 @test18(i64 %A) {
%0:
  %C = trunc i64 %A to i54
  ret i54 %C
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:
i64 %A = #xffdfffffffffffff (18437736874454810623, -9007199254740993)

Source:
double %B = #xc340000000000000 (-9007199254740992)
i54 %C = #x20000000000000 (9007199254740992, -9007199254740992)

Target:
i54 %C = #x1fffffffffffff (9007199254740991)
Source value: #x20000000000000 (9007199254740992, -9007199254740992)
Target value: #x1fffffffffffff (9007199254740991)

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
regehr@john-home:~$ 

cc @aqjune @nunoplopes @ryan-berger @nbushehri @zhengyang92

@regehr
Copy link
Contributor Author

regehr commented Apr 27, 2022

(I should have added that you don't need to believe alive2 about the change in output, we verified this independently, splitting the roundtrip across functions to defeat the backend optimizations)

Johns-MacBook-Pro:~ regehr$ cat foo.c
#include <stdio.h>

unsigned long src(unsigned long);
unsigned long srcX(unsigned long);
unsigned long tgt(unsigned long);

int main(void) {
  unsigned long val = 18437736874454810623UL;
  unsigned long x = src(val);
  unsigned long z = srcX(val);
  unsigned long y = tgt(val);
  printf("%lx %lx %lx %lx\n", x, z, y, val);
  return 0;
}

Johns-MacBook-Pro:~ regehr$ cat foo.ll
define i64 @src(i64 %A) {
  %B = sitofp i64 %A to double
  %C = fptosi double %B to i54
  %D = zext i54 %C to i64
  ret i64 %D
}

define i54 @srcY(double %A) {
  %C = fptosi double %A to i54
  ret i54 %C
}

define i64 @srcX(i64 %A) {
  %B = sitofp i64 %A to double
  %C = call i54 @srcY(double %B)
  %D = zext i54 %C to i64
  ret i64 %D
}

define i64 @tgt(i64 %A) {
  %C = trunc i64 %A to i54
  %D = zext i54 %C to i64
  ret i64 %D
}
Johns-MacBook-Pro:~ regehr$ llc foo.ll && clang foo.s foo.c && ./a.out
1fffffffffffff 20000000000000 1fffffffffffff ffdfffffffffffff
Johns-MacBook-Pro:~ regehr$ 

@efriedma-quic
Copy link
Collaborator

Looks like an off-by-one error. LLVM doesn't do the optimization for i55, and I think the transformation is correct for i53.

@regehr
Copy link
Contributor Author

regehr commented Apr 27, 2022

Looks like an off-by-one error. LLVM doesn't do the optimization for i55, and I think the transformation is correct for i53.

this sounds right to me

@rotateright
Copy link
Contributor

The instcombine bug appears to go back to before LLVM 3.9:
b9a0fa4

@fhahn fhahn changed the title likely incorrect optimization of sitofp/fptosi roundtrip [InstCombine] likely incorrect optimization of sitofp/fptosi roundtrip Apr 29, 2022
rotateright added a commit that referenced this issue Apr 29, 2022
This overlaps with at least some existing tests,
but the smaller types should be faster for alive2
to verify. We know that at least one of these is
currently wrong (miscompile) as shown in #55150.
@rotateright
Copy link
Contributor

@rotateright
Copy link
Contributor

The same fold was added to DAGCombiner around the same time, so that's why it shows up in codegen too:
3e0023b

I can push another patch for that once we have an approved patch for instcombine.

rotateright added a commit that referenced this issue May 2, 2022
Adapted from tests for IR in D124692.
Also see #55150
rotateright added a commit that referenced this issue May 2, 2022
Copied from x86 tests for multi-target coverage.
Also, provides coverage for target-specific asm
testing for Alive2 or its follow-ons.

See #55150 and D124692
@rotateright rotateright self-assigned this May 2, 2022
@rotateright
Copy link
Contributor

rotateright added a commit that referenced this issue May 2, 2022
This is the codegen equivalent of D124692.

As shown in #55150 -
the existing fold may be wrong when converting to a signed value.
This is a quick fix to avoid the miscompile.
https://alive2.llvm.org/ce/z/KtaDmd

Differential Revision: https://reviews.llvm.org/D124771
mem-frob pushed a commit to draperlaboratory/hope-llvm-project that referenced this issue Oct 7, 2022
As shown in llvm/llvm-project#55150 -
the existing fold may be wrong when converting to a signed value.
This is a quick fix to avoid the miscompile.

I added tests/comments for all of the signed/unsigned combinations
at either side of the boundary width, and tried to confirm with Alive2:
https://alive2.llvm.org/ce/z/3p9DSu

There are already some TODO items in the test file that suggest
possible refinements, so the regression with ui->FP->si is probably ok.
It seems unlikely that we'd see these kind of edge cases with
non-byte-width integer types in real code. The potential miscompile
went undetected for several years.

This and 747c6a0c734e fixes #55150.

Differential Revision: https://reviews.llvm.org/D124692
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants