This is an archive of the discontinued LLVM Phabricator instance.

[mips] Fix an issue with long double when function roundl is defined
ClosedPublic

Authored by zbuljan on Mar 1 2016, 5:19 AM.

Details

Summary

Patch adds roundl to a list of library calls in isF128SoftLibCall method (MipsCCState.cpp).
Test file roundl-call.ll is also added to LLVM regression tests.

Problem description:
There was a problem in LLVM backend that is triggered with next C code:

#include <math.h>

int main() {
  long double x, y;
  y = roundl(x);
  return 0;
}

With clang we generate IR code using -emit-llvm option (roundl-call.ll):

clang -static -O0 --target=mips64-img-linux-gnu -EL -mcpu=mips64r6 -mabi=64 -mhard-float -no-integrated-as --gcc-toolchain=/home/rtrk/mips-toolchain/mips-img-linux-gnu/2015.01-7 -S -emit-llvm roundl-test.c

Then we generate assembler code from roundl-call.ll with llc:

llc -march=mips64el -mcpu=mips64r3 -target-abi=n64 -O2 < roundl-call.ll

We can see that generated assembler code is using the wrong convention for roundl call.

Soft-float registers V0_64 and V1_64 are used for storing result instead of hard-float registers:

sd  $3, 8($fp)
sd  $2, 0($fp)

After the patch is applied we generate assembler code again from the same .ll file.
Now we can see that FPU registers D0_64 and D2_64 are used as it is expected for hard-float:

sdc1  $f2, 8($fp)
sdc1  $f0, 0($fp)

*This bug is also reported on bugzilla (https://dmz-portal.mips.com/bugz/show_bug.cgi?id=2303).

Diff Detail

Repository
rL LLVM

Event Timeline

zbuljan updated this revision to Diff 49476.Mar 1 2016, 5:19 AM
zbuljan retitled this revision from to [mips] Fix an issue with long double when function roundl is defined.
zbuljan updated this object.
zbuljan added subscribers: petarj, llvm-commits.
zbuljan updated this object.Mar 1 2016, 11:38 PM
zbuljan edited edge metadata.
dsanders edited edge metadata.Mar 2 2016, 5:46 AM
#include <math.h>

int main() {
  long double x, y;
  y = roundl(x);
  return 0;
}

The majority of the function is dead code and x is uninitialized.

clang -static -O0 --target=mips64-img-linux-gnu -EL -mcpu=mips64r6 -mabi=64 -mhard-float -no-integrated-as --gcc-toolchain=/home/rtrk/mips-toolchain/mips-img-linux-gnu/2015.01-7 -S -emit-llvm roundl-test.c

Then we generate assembler code from roundl-call.ll with llc:

llc -march=mips64el -mcpu=mips64r3 -target-abi=n64 -O2 < roundl-call.ll

I notice these two commands use different CPU's and that the ISA's for the two are incompatible.

test/CodeGen/Mips/roundl-call.ll
1 ↗(On Diff #49476)

Can you put calling convention tests in test/CodeGen/Mips/cconv/?

return-hard-fp128.ll and arguments-hard-fp128.ll are the fp128 hard-float tests. Could you test in a similar way to those two?
In particular:

  • We need to cover N32.
  • We need to ensure that soft-float still works correctly.
  • We don't need to test mips64r2/mips64r3 explicitly since there's no difference compared to mips64.
  • We should eliminate as much unnecessary code as possible. There's usually no need for alloca's, loads, stores, attributes, etc. in these tests.
zbuljan updated this revision to Diff 49803.Mar 4 2016, 1:54 AM
zbuljan edited edge metadata.

Updated .ll with tests for N32 and soft-float.
Removed unnecessary IR code.
.ll file moved to test/CodeGen/Mips/cconv/ folder.

dsanders accepted this revision.Mar 11 2016, 6:51 AM
dsanders edited edge metadata.

LGTM

This revision is now accepted and ready to land.Mar 11 2016, 6:51 AM
This revision was automatically updated to reflect the committed changes.