Fix ppcf128 component access on little-endian systems
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 3 Jul 2014 15:06:47 +0000 (15:06 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 3 Jul 2014 15:06:47 +0000 (15:06 +0000)
commitf236bb1b5bea26acbcb39f8232e64c638904bc82
treedc8e6dac3c30a92f1ce47122e330e3a45b90734c
parent4af9c0ea80632238563ea99d9662ded44be4e89c
Fix ppcf128 component access on little-endian systems

The PowerPC 128-bit long double data type (ppcf128 in LLVM) is in fact a
pair of two doubles, where one is considered the "high" or
more-significant part, and the other is considered the "low" or
less-significant part.  When a ppcf128 value is stored in memory or a
register pair, the high part always comes first, i.e. at the lower
memory address or in the lower-numbered register, and the low part
always comes second.  This is true both on big-endian and little-endian
PowerPC systems.  (Similar to how with a complex number, the real part
always comes first and the imaginary part second, no matter the byte
order of the system.)

This was implemented incorrectly for little-endian systems in LLVM.
This commit fixes three related issues:

- When printing an immediate ppcf128 constant to assembler output
  in emitGlobalConstantFP, emit the high part first on both big-
  and little-endian systems.

- When lowering a ppcf128 type to a pair of f64 types in SelectionDAG
  (which is used e.g. when generating code to load an argument into a
  register pair), use correct low/high part ordering on little-endian
  systems.

- In a related issue, because lowering ppcf128 into a pair of f64 must
  operate differently from lowering an int128 into a pair of i64,
  bitcasts between ppcf128 and int128 must not be optimized away by the
  DAG combiner on little-endian systems, but must effect a word-swap.

Reviewed by Hal Finkel.

llvm-svn: 212274
llvm/include/llvm/Target/TargetLowering.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/test/CodeGen/PowerPC/ppcf128-endian.ll [new file with mode: 0644]
llvm/test/CodeGen/X86/float-asmprint.ll