diff options
| author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2014-07-03 15:06:47 +0000 |
|---|---|---|
| committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2014-07-03 15:06:47 +0000 |
| commit | f236bb1b5bea26acbcb39f8232e64c638904bc82 (patch) | |
| tree | dc8e6dac3c30a92f1ce47122e330e3a45b90734c /llvm/test/CodeGen | |
| parent | 4af9c0ea80632238563ea99d9662ded44be4e89c (diff) | |
| download | bcm5719-llvm-f236bb1b5bea26acbcb39f8232e64c638904bc82.tar.gz bcm5719-llvm-f236bb1b5bea26acbcb39f8232e64c638904bc82.zip | |
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
Diffstat (limited to 'llvm/test/CodeGen')
| -rw-r--r-- | llvm/test/CodeGen/PowerPC/ppcf128-endian.ll | 154 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/float-asmprint.ll | 5 |
2 files changed, 157 insertions, 2 deletions
diff --git a/llvm/test/CodeGen/PowerPC/ppcf128-endian.ll b/llvm/test/CodeGen/PowerPC/ppcf128-endian.ll new file mode 100644 index 00000000000..2a5f13a5c3d --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/ppcf128-endian.ll @@ -0,0 +1,154 @@ +; RUN: llc -mcpu=pwr7 -mattr=+altivec < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-n32:64" +target triple = "powerpc64le-unknown-linux-gnu" + +@g = common global ppc_fp128 0xM00000000000000000000000000000000, align 16 + +define void @callee(ppc_fp128 %x) { +entry: + %x.addr = alloca ppc_fp128, align 16 + store ppc_fp128 %x, ppc_fp128* %x.addr, align 16 + %0 = load ppc_fp128* %x.addr, align 16 + store ppc_fp128 %0, ppc_fp128* @g, align 16 + ret void +} +; CHECK: @callee +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK: stfd 2, 8([[REG]]) +; CHECK: stfd 1, 0([[REG]]) +; CHECK: blr + +define void @caller() { +entry: + %0 = load ppc_fp128* @g, align 16 + call void @test(ppc_fp128 %0) + ret void +} +; CHECK: @caller +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK: lfd 2, 8([[REG]]) +; CHECK: lfd 1, 0([[REG]]) +; CHECK: bl test + +declare void @test(ppc_fp128) + +define void @caller_const() { +entry: + call void @test(ppc_fp128 0xM3FF00000000000000000000000000000) + ret void +} +; CHECK: .LCPI[[LC:[0-9]+]]_0: +; CHECK: .long 1065353216 +; CHECK: .LCPI[[LC]]_1: +; CHECK: .long 0 +; CHECK: @caller_const +; CHECK: addi [[REG0:[0-9]+]], {{[0-9]+}}, .LCPI[[LC]]_0 +; CHECK: addi [[REG1:[0-9]+]], {{[0-9]+}}, .LCPI[[LC]]_1 +; CHECK: lfs 1, 0([[REG0]]) +; CHECK: lfs 2, 0([[REG1]]) +; CHECK: bl test + +define ppc_fp128 @result() { +entry: + %0 = load ppc_fp128* @g, align 16 + ret ppc_fp128 %0 +} +; CHECK: @result +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK: lfd 1, 0([[REG]]) +; CHECK: lfd 2, 8([[REG]]) +; CHECK: blr + +define void @use_result() { +entry: + %call = tail call ppc_fp128 @test_result() #3 + store ppc_fp128 %call, ppc_fp128* @g, align 16 + ret void +} +; CHECK: @use_result +; CHECK: bl test_result +; CHECK: ld [[REG:[0-9]+]], .LC +; CHECK: stfd 2, 8([[REG]]) +; CHECK: stfd 1, 0([[REG]]) +; CHECK: blr + +declare ppc_fp128 @test_result() + +define void @caller_result() { +entry: + %call = tail call ppc_fp128 @test_result() + tail call void @test(ppc_fp128 %call) + ret void +} +; CHECK: @caller_result +; CHECK: bl test_result +; CHECK-NEXT: nop +; CHECK-NEXT: bl test +; CHECK-NEXT: nop + +define i128 @convert_from(ppc_fp128 %x) { +entry: + %0 = bitcast ppc_fp128 %x to i128 + ret i128 %0 +} +; CHECK: @convert_from +; CHECK: stfd 1, [[OFF1:.*]](1) +; CHECK: stfd 2, [[OFF2:.*]](1) +; CHECK: ld 3, [[OFF1]](1) +; CHECK: ld 4, [[OFF2]](1) +; CHECK: blr + +define ppc_fp128 @convert_to(i128 %x) { +entry: + %0 = bitcast i128 %x to ppc_fp128 + ret ppc_fp128 %0 +} +; CHECK: @convert_to +; CHECK: std 3, [[OFF1:.*]](1) +; CHECK: std 4, [[OFF2:.*]](1) +; CHECK: lfd 1, [[OFF1]](1) +; CHECK: lfd 2, [[OFF2]](1) +; CHECK: blr + +define ppc_fp128 @convert_to2(i128 %x) { +entry: + %shl = shl i128 %x, 1 + %0 = bitcast i128 %shl to ppc_fp128 + ret ppc_fp128 %0 +} + +; CHECK: @convert_to +; CHECK: std 3, [[OFF1:.*]](1) +; CHECK: std 4, [[OFF2:.*]](1) +; CHECK: lfd 1, [[OFF1]](1) +; CHECK: lfd 2, [[OFF2]](1) +; CHECK: blr + +define double @convert_vector(<4 x i32> %x) { +entry: + %cast = bitcast <4 x i32> %x to ppc_fp128 + %conv = fptrunc ppc_fp128 %cast to double + ret double %conv +} +; CHECK: @convert_vector +; CHECK: addi [[REG:[0-9]+]], 1, [[OFF:.*]] +; CHECK: stvx 2, 0, [[REG]] +; CHECK: lfd 1, [[OFF]](1) +; CHECK: blr + +declare void @llvm.va_start(i8*) + +define double @vararg(i32 %a, ...) { +entry: + %va = alloca i8*, align 8 + %va1 = bitcast i8** %va to i8* + call void @llvm.va_start(i8* %va1) + %arg = va_arg i8** %va, ppc_fp128 + %conv = fptrunc ppc_fp128 %arg to double + ret double %conv +} +; CHECK: @vararg +; CHECK: lfd 1, 0({{[0-9]+}}) +; CHECK: blr + diff --git a/llvm/test/CodeGen/X86/float-asmprint.ll b/llvm/test/CodeGen/X86/float-asmprint.ll index 4aeae7fe046..5de9700fc06 100644 --- a/llvm/test/CodeGen/X86/float-asmprint.ll +++ b/llvm/test/CodeGen/X86/float-asmprint.ll @@ -16,8 +16,9 @@ ; CHECK-NEXT: .size ; CHECK: varppc128: -; CHECK-NEXT: .quad 0 # ppc_fp128 -0 -; CHECK-NEXT: .quad -9223372036854775808 +; For ppc_fp128, the high double always comes first. +; CHECK-NEXT: .quad -9223372036854775808 # ppc_fp128 -0 +; CHECK-NEXT: .quad 0 ; CHECK-NEXT: .size ; CHECK: var80: |

