Skip to content

[LSR] Seemingly incorrect folding #134305

@ashermancinelli

Description

@ashermancinelli

https://godbolt.org/z/3834noxac

You can link and run this test if you have the fortran runtime built (flang test.ll before and after LSR). The essence is that we convert from i64->fp128->i64 and check that the round trip was exact, and if not, abort with failure message.

;; before
3:                                                ; preds = %16, %0
  %.014 = phi i64 [ 100, %0 ], [ %17, %16 ]
  %.0913 = phi i64 [ 9223372026854775807, %0 ], [ %18, %16 ]

  ; When this is an sitofp, loop-reduce doesn't do anything weird
  %4 = uitofp i64 %.0913 to fp128
  %5 = tail call i64 @llvm.fptosi.sat.i64.f128(fp128 %4)
  %.not = icmp eq i64 %5, %.0913
  br i1 %.not, label %12, label %6

;; after
3:                                                ; preds = %16, %0
  %lsr.iv1 = phi i64 [ %lsr.iv.next2, %16 ], [ 9223372026954775807, %0 ]
  %lsr.iv = phi i64 [ %lsr.iv.next, %16 ], [ -100, %0 ]
  %IV.S. = phi fp128 [ 0xL7000000000000000403DFFFFFFF6AFD0, %0 ], [ %IV.S.next., %16 ]
  %4 = add i64 %lsr.iv1, -100000000
  %5 = tail call i64 @llvm.fptosi.sat.i64.f128(fp128 %IV.S.)
  %.not = icmp eq i64 %4, %5
  br i1 %.not, label %13, label %split

With a little libquadmath test program, it looks like 0xL7000000000000000403DFFFFFFF6AFD0 is one greater than %4, which causes this test to fail.

9223372026954775807 | %lsr.iv1 on entry
         -100000000 |
------------------- |
9223372026854775807 | %4
                    |
9223372026854775808 | this hex value converted to int
                    | 0xL7000000000000000403DFFFFFFF6AFD0

Extra context: In the IR flang outputs directly after lowering from mlir, the int to float conversion is an sitofp instruction, but instcombine changes this to a uitofp earlier in the pipeline. If we change the uitofp back into an sitofp in the godbolt then we get a passing test again.

This is the Fortran source:

real(kind=16) dd, lowest, highest
integer(kind=8) :: i, incr, big
integer :: n = 100
incr = 100000000_8
do i = huge(i) - 10000000000_8,huge(i)-incr,incr
  if (int(real(i,kind=16),kind=8).ne.i) then
  print *,i,real(i,kind=16),int(real(i,kind=16),kind=8)
  stop 'FAIL'
  endif
enddo
print *,'ok'
end

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions