diff options
author | Stephen Hines <srhines@google.com> | 2014-12-01 14:51:49 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-12-02 16:08:10 -0800 |
commit | 37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch) | |
tree | 8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /test/CodeGen/Mips | |
parent | d2327b22152ced7bc46dc629fc908959e8a52d03 (diff) | |
download | external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2 |
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'test/CodeGen/Mips')
72 files changed, 4220 insertions, 451 deletions
diff --git a/test/CodeGen/Mips/Fast-ISel/br1.ll b/test/CodeGen/Mips/Fast-ISel/br1.ll new file mode 100644 index 0000000..579a77f --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/br1.ll @@ -0,0 +1,34 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@b = global i32 1, align 4 +@i = global i32 0, align 4 +@.str = private unnamed_addr constant [5 x i8] c"%i \0A\00", align 1 + +; Function Attrs: nounwind +define void @br() #0 { +entry: + %0 = load i32* @b, align 4 + %tobool = icmp eq i32 %0, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + store i32 6754, i32* @i, align 4 + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +; FIXME: This instruction is redundant. +; CHECK: xor $[[REG1:[0-9]+]], ${{[0-9]+}}, $zero +; CHECK: sltiu $[[REG2:[0-9]+]], $[[REG1]], 1 +; CHECK: bgtz $[[REG2]], $BB[[BL:[0-9]+_[0-9]+]] +; CHECK: nop +; CHECK: addiu ${{[0-9]+}}, $zero, 6754 +; CHECK: sw ${{[0-9]+}}, 0(${{[0-9]+}}) +; CHECK: $BB[[BL]]: + +} + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/CodeGen/Mips/Fast-ISel/callabi.ll b/test/CodeGen/Mips/Fast-ISel/callabi.ll new file mode 100644 index 0000000..44b94bb --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/callabi.ll @@ -0,0 +1,477 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32r2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=CHECK2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=CHECK2 + + +@c1 = global i8 -45, align 1 +@uc1 = global i8 27, align 1 +@s1 = global i16 -1789, align 2 +@us1 = global i16 1256, align 2 + +; Function Attrs: nounwind +define void @cxi() #0 { +entry: +; CHECK-LABEL: cxi + call void @xi(i32 10) +; CHECK-DAG: addiu $4, $zero, 10 +; CHECK-DAG: lw $25, %got(xi)(${{[0-9]+}}) +; CHECK: jalr $25 + + ret void +} + +declare void @xi(i32) #1 + +; Function Attrs: nounwind +define void @cxii() #0 { +entry: +; CHECK-LABEL: cxii + call void @xii(i32 746, i32 892) +; CHECK-DAG: addiu $4, $zero, 746 +; CHECK-DAG: addiu $5, $zero, 892 +; CHECK-DAG: lw $25, %got(xii)(${{[0-9]+}}) +; CHECK: jalr $25 + + ret void +} + +declare void @xii(i32, i32) #1 + +; Function Attrs: nounwind +define void @cxiii() #0 { +entry: +; CHECK-LABEL: cxiii + call void @xiii(i32 88, i32 44, i32 11) +; CHECK-DAG: addiu $4, $zero, 88 +; CHECK-DAG: addiu $5, $zero, 44 +; CHECK-DAG: addiu $6, $zero, 11 +; CHECK-DAG: lw $25, %got(xiii)(${{[0-9]+}}) +; CHECK: jalr $25 + ret void +} + +declare void @xiii(i32, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxiiii() #0 { +entry: +; CHECK-LABEL: cxiiii + call void @xiiii(i32 167, i32 320, i32 97, i32 14) +; CHECK-DAG: addiu $4, $zero, 167 +; CHECK-DAG: addiu $5, $zero, 320 +; CHECK-DAG: addiu $6, $zero, 97 +; CHECK-DAG: addiu $7, $zero, 14 +; CHECK-DAG: lw $25, %got(xiiii)(${{[0-9]+}}) +; CHECK: jalr $25 + + ret void +} + +declare void @xiiii(i32, i32, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxiiiiconv() #0 { +entry: +; CHECK-LABEL: cxiiiiconv +; mips32r2-LABEL: cxiiiiconv +; mips32-LABEL: cxiiiiconv + %0 = load i8* @c1, align 1 + %conv = sext i8 %0 to i32 + %1 = load i8* @uc1, align 1 + %conv1 = zext i8 %1 to i32 + %2 = load i16* @s1, align 2 + %conv2 = sext i16 %2 to i32 + %3 = load i16* @us1, align 2 + %conv3 = zext i16 %3 to i32 + call void @xiiii(i32 %conv, i32 %conv1, i32 %conv2, i32 %conv3) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2-DAG: lw $[[REG_C1_ADDR:[0-9]+]], %got(c1)($[[REG_GP]]) +; mips32r2-DAG: lbu $[[REG_C1:[0-9]+]], 0($[[REG_C1_ADDR]]) +; mips32r2-DAG seb $3, $[[REG_C1]] +; mips32-DAG: lw $[[REG_C1_ADDR:[0-9]+]], %got(c1)($[[REG_GP]]) +; mips32-DAG: lbu $[[REG_C1:[0-9]+]], 0($[[REG_C1_ADDR]]) +; mips32-DAG: sll $[[REG_C1_1:[0-9]+]], $[[REG_C1]], 24 +; mips32-DAG: sra $4, $[[REG_C1_1]], 24 +; CHECK-DAG: lw $[[REG_UC1_ADDR:[0-9]+]], %got(uc1)($[[REG_GP]]) +; CHECK-DAG: lbu $[[REG_UC1:[0-9]+]], 0($[[REG_UC1_ADDR]]) +; FIXME andi is superfulous +; CHECK-DAG: andi $5, $[[REG_UC1]], 255 +; mips32r2-DAG: lw $[[REG_S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]]) +; mips32r2-DAG: lhu $[[REG_S1:[0-9]+]], 0($[[REG_S1_ADDR]]) +; mips32r2-DAG: seh $6, $[[REG_S1]] +; mips32-DAG: lw $[[REG_S1_ADDR:[0-9]+]], %got(s1)($[[REG_GP]]) +; mips32-DAG: lhu $[[REG_S1:[0-9]+]], 0($[[REG_S1_ADDR]]) +; mips32-DAG: sll $[[REG_S1_1:[0-9]+]], $[[REG_S1]], 16 +; mips32-DAG: sra $6, $[[REG_S1_1]], 16 +; CHECK-DAG: lw $[[REG_US1_ADDR:[0-9]+]], %got(us1)($[[REG_GP]]) +; CHECK-DAG: lhu $[[REG_US1:[0-9]+]], 0($[[REG_US1_ADDR]]) +; FIXME andi is superfulous +; CHECK-DAG: andi $7, $[[REG_US1]], 65535 +; mips32r2: jalr $25 +; mips32r2: jalr $25 +; CHECK: jalr $25 + ret void +} + +; Function Attrs: nounwind +define void @cxf() #0 { +entry: +; CHECK-LABEL: cxf + call void @xf(float 0x40BBC85560000000) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK: lui $[[REG_FPCONST_1:[0-9]+]], 17886 +; CHECK: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 17067 +; CHECK: mtc1 $[[REG_FPCONST]], $f12 +; CHECK: lw $25, %got(xf)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xf(float) #1 + +; Function Attrs: nounwind +define void @cxff() #0 { +entry: +; CHECK-LABEL: cxff + call void @xff(float 0x3FF74A6CA0000000, float 0x401A2C0840000000) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16314 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 21349 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: lui $[[REG_FPCONST_2:[0-9]+]], 16593 +; CHECK-DAG: ori $[[REG_FPCONST_3:[0-9]+]], $[[REG_FPCONST_2]], 24642 +; CHECK-DAG: mtc1 $[[REG_FPCONST_3]], $f14 +; CHECK: lw $25, %got(xff)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xff(float, float) #1 + +; Function Attrs: nounwind +define void @cxfi() #0 { +entry: +; CHECK-LABEL: cxfi + call void @xfi(float 0x4013906240000000, i32 102) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16540 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 33554 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: addiu $5, $zero, 102 +; CHECK: lw $25, %got(xfi)($[[REG_GP]]) +; CHECK: jalr $25 + + ret void +} + +declare void @xfi(float, i32) #1 + +; Function Attrs: nounwind +define void @cxfii() #0 { +entry: +; CHECK-LABEL: cxfii + call void @xfii(float 0x405EC7EE00000000, i32 9993, i32 10922) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 17142 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 16240 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: addiu $5, $zero, 9993 +; CHECK-DAG: addiu $6, $zero, 10922 +; CHECK: lw $25, %got(xfii)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xfii(float, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxfiii() #0 { +entry: +; CHECK-LABEL: cxfiii + call void @xfiii(float 0x405C072B20000000, i32 3948, i32 89011, i32 111222) +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 17120 +; CHECK-DAG: ori $[[REG_FPCONST:[0-9]+]], $[[REG_FPCONST_1]], 14681 +; CHECK-DAG: mtc1 $[[REG_FPCONST]], $f12 +; CHECK-DAG: addiu $5, $zero, 3948 +; CHECK-DAG: lui $[[REG_I_1:[0-9]+]], 1 +; CHECK-DAG: ori $6, $[[REG_I_1]], 23475 +; CHECK-DAG: lui $[[REG_I_2:[0-9]+]], 1 +; CHECK-DAG: ori $7, $[[REG_I_2]], 45686 +; CHECK: lw $25, %got(xfiii)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xfiii(float, i32, i32, i32) #1 + +; Function Attrs: nounwind +define void @cxd() #0 { +entry: +; mips32r2-LABEL: cxd: +; mips32-LABEL: cxd: + call void @xd(double 5.994560e+02) +; mips32: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16514 +; mips32-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 48037 +; mips32-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 58195 +; mips32-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 63439 +; mips32-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32-DAG: mtc1 $[[REG_FPCONST_2]], $f13 +; mips32-DAG: lw $25, %got(xd)($[[REG_GP]]) +; mips32: jalr $25 +; mips32r2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16514 +; mips32r2-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 48037 +; mips32r2-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 58195 +; mips32r2-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 63439 +; mips32r2-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32r2-DAG: mthc1 $[[REG_FPCONST_2]], $f12 +; mips32r2-DAG: lw $25, %got(xd)($[[REG_GP]]) +; mips32r2 : jalr $25 + ret void +} + +declare void @xd(double) #1 + +; Function Attrs: nounwind +define void @cxdd() #0 { +; mips32r2-LABEL: cxdd: +; mips32-LABEL: cxdd: +entry: + call void @xdd(double 1.234980e+03, double 0x40F5B331F7CED917) +; mips32: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16531 +; mips32-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 19435 +; mips32-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 34078 +; mips32-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 47186 +; mips32-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32-DAG: mtc1 $[[REG_FPCONST_2]], $f13 +; mips32-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16629 +; mips32-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 45873 +; mips32-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 63438 +; mips32-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 55575 +; mips32-DAG: mtc1 $[[REG_FPCONST_4]], $f14 +; mips32-DAG: mtc1 $[[REG_FPCONST_2]], $f15 +; mips32-DAG: lw $25, %got(xdd)($[[REG_GP]]) +; mips32: jalr $25 +; mips32r2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; mips32r2-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16531 +; mips32r2-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 19435 +; mips32r2-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 34078 +; mips32r2-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 47186 +; mips32r2-DAG: mtc1 $[[REG_FPCONST_4]], $f12 +; mips32r2-DAG: mthc1 $[[REG_FPCONST_2]], $f12 +; mips32r2-DAG: lui $[[REG_FPCONST_1:[0-9]+]], 16629 +; mips32r2-DAG: ori $[[REG_FPCONST_2:[0-9]+]], $[[REG_FPCONST_1]], 45873 +; mips32r2-DAG: lui $[[REG_FPCONST_3:[0-9]+]], 63438 +; mips32r2-DAG: ori $[[REG_FPCONST_4:[0-9]+]], $[[REG_FPCONST_3]], 55575 +; mips32r2-DAG: mtc1 $[[REG_FPCONST_4]], $f14 +; mips32r2-DAG: mthc1 $[[REG_FPCONST_2]], $f14 +; mips32r2-DAG: lw $25, %got(xdd)($[[REG_GP]]) +; mips32r2 : jalr $25 + ret void +} + +declare void @xdd(double, double) #1 + +; Function Attrs: nounwind +define void @cxif() #0 { +entry: +; CHECK-LABEL: cxif: + call void @xif(i32 345, float 0x407BCE5A20000000) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 345 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 17374 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 29393 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECK-DAG: lw $25, %got(xif)($[[REG_GP]]) +; CHECK: jalr $25 + + ret void +} + +declare void @xif(i32, float) #1 + +; Function Attrs: nounwind +define void @cxiff() #0 { +entry: +; CHECK-LABEL: cxiff: +; CHECK2-LABEL: cxiff: + call void @xiff(i32 12239, float 0x408EDB3340000000, float 0x4013FFE5C0000000) +; We need to do the two floating point parameters in a separate +; check because we can't control the ordering of parts of the sequence +;; +; CHECK: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK: addiu $4, $zero, 12239 +; CHECK2: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK2: addiu $4, $zero, 12239 +; CHECK: lui $[[REGF_1:[0-9]+]], 17526 +; CHECK: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 55706 +; CHECK: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK: mfc1 $5, $f[[REGF_3]] +; CHECK2: lui $[[REGF2_1:[0-9]+]], 16543 +; CHECK2: ori $[[REGF2_2:[0-9]+]], $[[REGF2_1]], 65326 +; CHECK2: mtc1 $[[REGF2_2]], $f[[REGF2_3:[0-9]+]] +; CHECK2: mfc1 $6, $f[[REGF2_3]] +; CHECK: lw $25, %got(xiff)($[[REG_GP]]) +; CHECK2: lw $25, %got(xiff)($[[REG_GP]]) +; CHECK: jalr $25 +; CHECK2: jalr $25 + ret void +} + +declare void @xiff(i32, float, float) #1 + +; Function Attrs: nounwind +define void @cxifi() #0 { +entry: +; CHECK: cxifi: + call void @xifi(i32 887, float 0x402277CEE0000000, i32 888) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 887 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 16659 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 48759 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECk-DAG: addiu $6, $zero, 888 +; CHECK-DAG: lw $25, %got(xifi)($[[REG_GP]]) +; CHECK: jalr $25 + + ret void +} + +declare void @xifi(i32, float, i32) #1 + +; Function Attrs: nounwind +define void @cxifif() #0 { +entry: +; CHECK: cxifif: +; CHECK2: cxifif: + call void @xifif(i32 67774, float 0x408EE0FBE0000000, i32 9991, float 0x40B15C8CC0000000) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: lui $[[REGI:[0-9]+]], 1 +; CHECK-DAG: ori $4, $[[REGI]], 2238 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 17527 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 2015 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECk-DAG: addiu $6, $zero, 888 +; CHECK2: lui $[[REGF2_1:[0-9]+]], 17802 +; CHECK2: ori $[[REGF2_2:[0-9]+]], $[[REGF2_1]], 58470 +; CHECK2: mtc1 $[[REGF2_2]], $f[[REGF2_3:[0-9]+]] +; CHECK2: mfc1 $7, $f[[REGF2_3]] +; CHECK: lw $25, %got(xifif)($[[REG_GP]]) +; CHECK2: lw $25, %got(xifif)($[[REG_GP]]) +; CHECK2: jalr $25 +; CHECK: jalr $25 + + ret void +} + +declare void @xifif(i32, float, i32, float) #1 + +; Function Attrs: nounwind +define void @cxiffi() #0 { +entry: +; CHECK-label: cxiffi: +; CHECK2-label: cxiffi: + call void @xiffi(i32 45, float 0x3FF6666660000000, float 0x408F333340000000, i32 234) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 45 +; CHECK2-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK2-DAG: addiu $4, $zero, 45 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 16307 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 13107 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECK2: lui $[[REGF2_1:[0-9]+]], 17529 +; CHECK2: ori $[[REGF2_2:[0-9]+]], $[[REGF2_1]], 39322 +; CHECK2: mtc1 $[[REGF2_2]], $f[[REGF2_3:[0-9]+]] +; CHECK2: mfc1 $6, $f[[REGF2_3]] +; CHECK-DAG: lw $25, %got(xiffi)($[[REG_GP]]) +; CHECK-DAG: addiu $7, $zero, 234 +; CHECK2-DAG: lw $25, %got(xiffi)($[[REG_GP]]) +; CHECK: jalr $25 +; CHECK2: jalr $25 + + ret void +} + +declare void @xiffi(i32, float, float, i32) #1 + +; Function Attrs: nounwind +define void @cxifii() #0 { +entry: +; CHECK-DAG: cxifii: + call void @xifii(i32 12239, float 0x408EDB3340000000, i32 998877, i32 1234) +; CHECK-DAG: addu $[[REG_GP:[0-9]+]], ${{[0-9]+}}, ${{[0-9+]}} +; CHECK-DAG: addiu $4, $zero, 12239 +; CHECK-DAG: lui $[[REGF_1:[0-9]+]], 17526 +; CHECK-DAG: ori $[[REGF_2:[0-9]+]], $[[REGF_1]], 55706 +; CHECK-DAG: mtc1 $[[REGF_2]], $f[[REGF_3:[0-9]+]] +; CHECK-DAG: mfc1 $5, $f[[REGF_3]] +; CHECK-DAG: lui $[[REGI2:[0-9]+]], 15 +; CHECK-DAG: ori $6, $[[REGI2]], 15837 +; CHECk-DAG: addiu $7, $zero, 1234 +; CHECK-DAG: lw $25, %got(xifii)($[[REG_GP]]) +; CHECK: jalr $25 + ret void +} + +declare void @xifii(i32, float, i32, i32) #1 + +; FIXME: this function will not pass yet. +; Function Attrs: nounwind +; define void @cxfid() #0 { +;entry: +; call void @xfid(float 0x4013B851E0000000, i32 811123, double 0x40934BFF487FCB92) +; ret void +;} + +declare void @xfid(float, i32, double) #1 + +; Function Attrs: nounwind +define void @g() #0 { +entry: + call void @cxi() + call void @cxii() + call void @cxiii() + call void @cxiiii() + call void @cxiiiiconv() + call void @cxf() + call void @cxff() + call void @cxd() + call void @cxfi() + call void @cxfii() + call void @cxfiii() + call void @cxdd() + call void @cxif() + call void @cxiff() + call void @cxifi() + call void @cxifii() + call void @cxifif() + call void @cxiffi() + ret void +} + + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.ident = !{!0} + +!0 = metadata !{metadata !"clang version 3.6.0 (gitosis@dmz-portal.mips.com:clang 43992fe7b17de5553ac06d323cb80cc6723a9ae3) (gitosis@dmz-portal.mips.com:llvm.git 0834e6839eb170197c81bb02e916258d1527e312)"} diff --git a/test/CodeGen/Mips/Fast-ISel/fpcmpa.ll b/test/CodeGen/Mips/Fast-ISel/fpcmpa.ll new file mode 100644 index 0000000..c72b1e7 --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/fpcmpa.ll @@ -0,0 +1,254 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@f1 = common global float 0.000000e+00, align 4 +@f2 = common global float 0.000000e+00, align 4 +@b1 = common global i32 0, align 4 +@d1 = common global double 0.000000e+00, align 8 +@d2 = common global double 0.000000e+00, align 8 + +; Function Attrs: nounwind +define void @feq1() { +entry: + %0 = load float* @f1, align 4 + %1 = load float* @f2, align 4 + %cmp = fcmp oeq float %0, %1 +; CHECK-LABEL: feq1: +; CHECK-DAG: lw $[[REG_F2_GOT:[0-9]+]], %got(f2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_F1_GOT:[0-9]+]], %got(f1)(${{[0-9]+}}) +; CHECK-DAG: lwc1 $f[[REG_F2:[0-9]+]], 0($[[REG_F2_GOT]]) +; CHECK-DAG: lwc1 $f[[REG_F1:[0-9]+]], 0($[[REG_F1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.eq.s $f[[REG_F1]], $f[[REG_F2]] +; CHECK: movt $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @fne1() { +entry: + %0 = load float* @f1, align 4 + %1 = load float* @f2, align 4 + %cmp = fcmp une float %0, %1 +; CHECK-LABEL: fne1: +; CHECK-DAG: lw $[[REG_F2_GOT:[0-9]+]], %got(f2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_F1_GOT:[0-9]+]], %got(f1)(${{[0-9]+}}) +; CHECK-DAG: lwc1 $f[[REG_F2:[0-9]+]], 0($[[REG_F2_GOT]]) +; CHECK-DAG: lwc1 $f[[REG_F1:[0-9]+]], 0($[[REG_F1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.eq.s $f[[REG_F1]], $f[[REG_F2]] +; CHECK: movf $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @flt1() { +entry: + %0 = load float* @f1, align 4 + %1 = load float* @f2, align 4 + %cmp = fcmp olt float %0, %1 +; CHECK-LABEL: flt1: +; CHECK-DAG: lw $[[REG_F2_GOT:[0-9]+]], %got(f2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_F1_GOT:[0-9]+]], %got(f1)(${{[0-9]+}}) +; CHECK-DAG: lwc1 $f[[REG_F2:[0-9]+]], 0($[[REG_F2_GOT]]) +; CHECK-DAG: lwc1 $f[[REG_F1:[0-9]+]], 0($[[REG_F1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.olt.s $f[[REG_F1]], $f[[REG_F2]] +; CHECK: movt $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @fgt1() { +entry: + %0 = load float* @f1, align 4 + %1 = load float* @f2, align 4 + %cmp = fcmp ogt float %0, %1 +; CHECK-LABEL: fgt1: +; CHECK-DAG: lw $[[REG_F2_GOT:[0-9]+]], %got(f2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_F1_GOT:[0-9]+]], %got(f1)(${{[0-9]+}}) +; CHECK-DAG: lwc1 $f[[REG_F2:[0-9]+]], 0($[[REG_F2_GOT]]) +; CHECK-DAG: lwc1 $f[[REG_F1:[0-9]+]], 0($[[REG_F1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.ule.s $f[[REG_F1]], $f[[REG_F2]] +; CHECK: movf $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @fle1() { +entry: + %0 = load float* @f1, align 4 + %1 = load float* @f2, align 4 + %cmp = fcmp ole float %0, %1 +; CHECK-LABEL: fle1: +; CHECK-DAG: lw $[[REG_F2_GOT:[0-9]+]], %got(f2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_F1_GOT:[0-9]+]], %got(f1)(${{[0-9]+}}) +; CHECK-DAG: lwc1 $f[[REG_F2:[0-9]+]], 0($[[REG_F2_GOT]]) +; CHECK-DAG: lwc1 $f[[REG_F1:[0-9]+]], 0($[[REG_F1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.ole.s $f[[REG_F1]], $f[[REG_F2]] +; CHECK: movt $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @fge1() { +entry: + %0 = load float* @f1, align 4 + %1 = load float* @f2, align 4 + %cmp = fcmp oge float %0, %1 +; CHECK-LABEL: fge1: +; CHECK-DAG: lw $[[REG_F2_GOT:[0-9]+]], %got(f2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_F1_GOT:[0-9]+]], %got(f1)(${{[0-9]+}}) +; CHECK-DAG: lwc1 $f[[REG_F2:[0-9]+]], 0($[[REG_F2_GOT]]) +; CHECK-DAG: lwc1 $f[[REG_F1:[0-9]+]], 0($[[REG_F1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.ult.s $f[[REG_F1]], $f[[REG_F2]] +; CHECK: movf $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @deq1() { +entry: + %0 = load double* @d1, align 8 + %1 = load double* @d2, align 8 + %cmp = fcmp oeq double %0, %1 +; CHECK-LABEL: deq1: +; CHECK-DAG: lw $[[REG_D2_GOT:[0-9]+]], %got(d2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D1_GOT:[0-9]+]], %got(d1)(${{[0-9]+}}) +; CHECK-DAG: ldc1 $f[[REG_D2:[0-9]+]], 0($[[REG_D2_GOT]]) +; CHECK-DAG: ldc1 $f[[REG_D1:[0-9]+]], 0($[[REG_D1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.eq.d $f[[REG_D1]], $f[[REG_D2]] +; CHECK: movt $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @dne1() { +entry: + %0 = load double* @d1, align 8 + %1 = load double* @d2, align 8 + %cmp = fcmp une double %0, %1 +; CHECK-LABEL: dne1: +; CHECK-DAG: lw $[[REG_D2_GOT:[0-9]+]], %got(d2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D1_GOT:[0-9]+]], %got(d1)(${{[0-9]+}}) +; CHECK-DAG: ldc1 $f[[REG_D2:[0-9]+]], 0($[[REG_D2_GOT]]) +; CHECK-DAG: ldc1 $f[[REG_D1:[0-9]+]], 0($[[REG_D1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.eq.d $f[[REG_D1]], $f[[REG_D2]] +; CHECK: movf $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @dlt1() { +entry: + %0 = load double* @d1, align 8 + %1 = load double* @d2, align 8 + %cmp = fcmp olt double %0, %1 +; CHECK-LABEL: dlt1: +; CHECK-DAG: lw $[[REG_D2_GOT:[0-9]+]], %got(d2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D1_GOT:[0-9]+]], %got(d1)(${{[0-9]+}}) +; CHECK-DAG: ldc1 $f[[REG_D2:[0-9]+]], 0($[[REG_D2_GOT]]) +; CHECK-DAG: ldc1 $f[[REG_D1:[0-9]+]], 0($[[REG_D1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.olt.d $f[[REG_D1]], $f[[REG_D2]] +; CHECK: movt $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @dgt1() { +entry: + %0 = load double* @d1, align 8 + %1 = load double* @d2, align 8 + %cmp = fcmp ogt double %0, %1 +; CHECK-LABEL: dgt1: +; CHECK-DAG: lw $[[REG_D2_GOT:[0-9]+]], %got(d2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D1_GOT:[0-9]+]], %got(d1)(${{[0-9]+}}) +; CHECK-DAG: ldc1 $f[[REG_D2:[0-9]+]], 0($[[REG_D2_GOT]]) +; CHECK-DAG: ldc1 $f[[REG_D1:[0-9]+]], 0($[[REG_D1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.ule.d $f[[REG_D1]], $f[[REG_D2]] +; CHECK: movf $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @dle1() { +entry: + %0 = load double* @d1, align 8 + %1 = load double* @d2, align 8 + %cmp = fcmp ole double %0, %1 +; CHECK-LABEL: dle1: +; CHECK-DAG: lw $[[REG_D2_GOT:[0-9]+]], %got(d2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D1_GOT:[0-9]+]], %got(d1)(${{[0-9]+}}) +; CHECK-DAG: ldc1 $f[[REG_D2:[0-9]+]], 0($[[REG_D2_GOT]]) +; CHECK-DAG: ldc1 $f[[REG_D1:[0-9]+]], 0($[[REG_D1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.ole.d $f[[REG_D1]], $f[[REG_D2]] +; CHECK: movt $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @dge1() { +entry: + %0 = load double* @d1, align 8 + %1 = load double* @d2, align 8 + %cmp = fcmp oge double %0, %1 +; CHECK-LABEL: dge1: +; CHECK-DAG: lw $[[REG_D2_GOT:[0-9]+]], %got(d2)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D1_GOT:[0-9]+]], %got(d1)(${{[0-9]+}}) +; CHECK-DAG: ldc1 $f[[REG_D2:[0-9]+]], 0($[[REG_D2_GOT]]) +; CHECK-DAG: ldc1 $f[[REG_D1:[0-9]+]], 0($[[REG_D1_GOT]]) +; CHECK-DAG: addiu $[[REG_ZERO:[0-9]+]], $zero, 0 +; CHECK-DAG: addiu $[[REG_ONE:[0-9]+]], $zero, 1 +; CHECK: c.ult.d $f[[REG_D1]], $f[[REG_D2]] +; CHECK: movf $[[REG_ZERO]], $[[REG_ONE]], $fcc0 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 + ret void +} + + diff --git a/test/CodeGen/Mips/Fast-ISel/fpext.ll b/test/CodeGen/Mips/Fast-ISel/fpext.ll new file mode 100644 index 0000000..98aca75 --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/fpext.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@f = global float 0x40147E6B80000000, align 4 +@d_f = common global double 0.000000e+00, align 8 +@.str = private unnamed_addr constant [6 x i8] c"%f \0A\00", align 1 + +; Function Attrs: nounwind +define void @dv() #0 { +entry: + %0 = load float* @f, align 4 + %conv = fpext float %0 to double +; CHECK: cvt.d.s $f{{[0-9]+}}, $f{{[0-9]+}} + store double %conv, double* @d_f, align 8 + ret void +} + + +attributes #1 = { nounwind } diff --git a/test/CodeGen/Mips/Fast-ISel/fpintconv.ll b/test/CodeGen/Mips/Fast-ISel/fpintconv.ll new file mode 100644 index 0000000..846726a --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/fpintconv.ll @@ -0,0 +1,35 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + + +@f = global float 0x40D6E83280000000, align 4 +@d = global double 0x4132D68780000000, align 8 +@i_f = common global i32 0, align 4 +@i_d = common global i32 0, align 4 +@.str = private unnamed_addr constant [5 x i8] c"%i \0A\00", align 1 + +; Function Attrs: nounwind +define void @ifv() { +entry: +; CHECK-LABEL: .ent ifv + %0 = load float* @f, align 4 + %conv = fptosi float %0 to i32 +; CHECK: trunc.w.s $f[[REG:[0-9]+]], $f{{[0-9]+}} +; CHECK: mfc1 ${{[0-9]+}}, $f[[REG]] + store i32 %conv, i32* @i_f, align 4 + ret void +} + +; Function Attrs: nounwind +define void @idv() { +entry: +; CHECK-LABEL: .ent idv + %0 = load double* @d, align 8 + %conv = fptosi double %0 to i32 +; CHECK: trunc.w.d $f[[REG:[0-9]+]], $f{{[0-9]+}} +; CHECK: mfc1 ${{[0-9]+}}, $f[[REG]] + store i32 %conv, i32* @i_d, align 4 + ret void +} diff --git a/test/CodeGen/Mips/Fast-ISel/fptrunc.ll b/test/CodeGen/Mips/Fast-ISel/fptrunc.ll new file mode 100644 index 0000000..d843dee --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/fptrunc.ll @@ -0,0 +1,20 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@d = global double 0x40147E6B74DF0446, align 8 +@f = common global float 0.000000e+00, align 4 +@.str = private unnamed_addr constant [6 x i8] c"%f \0A\00", align 1 + +; Function Attrs: nounwind +define void @fv() #0 { +entry: + %0 = load double* @d, align 8 + %conv = fptrunc double %0 to float +; CHECK: cvt.s.d $f{{[0-9]+}}, $f{{[0-9]+}} + store float %conv, float* @f, align 4 + ret void +} + +attributes #1 = { nounwind } diff --git a/test/CodeGen/Mips/Fast-ISel/icmpa.ll b/test/CodeGen/Mips/Fast-ISel/icmpa.ll new file mode 100644 index 0000000..bd41a29 --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/icmpa.ll @@ -0,0 +1,210 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@c = global i32 4, align 4 +@d = global i32 9, align 4 +@uc = global i32 4, align 4 +@ud = global i32 9, align 4 +@b1 = common global i32 0, align 4 + +; Function Attrs: nounwind +define void @eq() { +entry: +; CHECK-LABEL: .ent eq + + %0 = load i32* @c, align 4 + %1 = load i32* @d, align 4 + %cmp = icmp eq i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_D_GOT:[0-9+]]], %got(d)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_C_GOT:[0-9+]]], %got(c)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D:[0-9]+]], 0($[[REG_D_GOT]]) +; CHECK-DAG: lw $[[REG_C:[0-9]+]], 0($[[REG_C_GOT]]) +; CHECK: xor $[[REG1:[0-9]+]], $[[REG_C]], $[[REG_D]] +; CHECK: sltiu $[[REG2:[0-9]+]], $[[REG1]], 1 +; FIXME: This instruction is redundant. The sltiu can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG2]], 1 + + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @ne() { +entry: +; CHECK-LABEL: .ent ne + %0 = load i32* @c, align 4 + %1 = load i32* @d, align 4 + %cmp = icmp ne i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_D_GOT:[0-9+]]], %got(d)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_C_GOT:[0-9+]]], %got(c)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D:[0-9]+]], 0($[[REG_D_GOT]]) +; CHECK-DAG: lw $[[REG_C:[0-9]+]], 0($[[REG_C_GOT]]) +; CHECK: xor $[[REG1:[0-9]+]], $[[REG_C]], $[[REG_D]] +; CHECK: sltu $[[REG2:[0-9]+]], $zero, $[[REG1]] +; FIXME: This instruction is redundant. The sltu can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG2]], 1 + + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @ugt() { +entry: +; CHECK-LABEL: .ent ugt + %0 = load i32* @uc, align 4 + %1 = load i32* @ud, align 4 + %cmp = icmp ugt i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_UD_GOT:[0-9+]]], %got(ud)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UC_GOT:[0-9+]]], %got(uc)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UD:[0-9]+]], 0($[[REG_UD_GOT]]) +; CHECK-DAG: lw $[[REG_UC:[0-9]+]], 0($[[REG_UC_GOT]]) +; CHECK: sltu $[[REG1:[0-9]+]], $[[REG_UD]], $[[REG_UC]] +; FIXME: This instruction is redundant. The sltu can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 1 + + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @ult() { +entry: +; CHECK-LABEL: .ent ult + %0 = load i32* @uc, align 4 + %1 = load i32* @ud, align 4 + %cmp = icmp ult i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_UD_GOT:[0-9+]]], %got(ud)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UC_GOT:[0-9+]]], %got(uc)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UD:[0-9]+]], 0($[[REG_UD_GOT]]) +; CHECK-DAG: lw $[[REG_UC:[0-9]+]], 0($[[REG_UC_GOT]]) +; CHECK: sltu $[[REG1:[0-9]+]], $[[REG_UC]], $[[REG_UD]] +; FIXME: This instruction is redundant. The sltu can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 1 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @uge() { +entry: +; CHECK-LABEL: .ent uge + %0 = load i32* @uc, align 4 + %1 = load i32* @ud, align 4 + %cmp = icmp uge i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_UD_GOT:[0-9+]]], %got(ud)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UC_GOT:[0-9+]]], %got(uc)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UD:[0-9]+]], 0($[[REG_UD_GOT]]) +; CHECK-DAG: lw $[[REG_UC:[0-9]+]], 0($[[REG_UC_GOT]]) +; CHECK: sltu $[[REG1:[0-9]+]], $[[REG_UC]], $[[REG_UD]] +; CHECK: xori $[[REG2:[0-9]+]], $[[REG1]], 1 +; FIXME: This instruction is redundant. The sltu can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG2]], 1 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @ule() { +entry: +; CHECK-LABEL: .ent ule + %0 = load i32* @uc, align 4 + %1 = load i32* @ud, align 4 + %cmp = icmp ule i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_UD_GOT:[0-9+]]], %got(ud)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UC_GOT:[0-9+]]], %got(uc)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_UD:[0-9]+]], 0($[[REG_UD_GOT]]) +; CHECK-DAG: lw $[[REG_UC:[0-9]+]], 0($[[REG_UC_GOT]]) +; CHECK: sltu $[[REG1:[0-9]+]], $[[REG_UD]], $[[REG_UC]] +; CHECK: xori $[[REG2:[0-9]+]], $[[REG1]], 1 +; FIXME: This instruction is redundant. The sltu can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG2]], 1 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @sgt() { +entry: +; CHECK-LABEL: .ent sgt + %0 = load i32* @c, align 4 + %1 = load i32* @d, align 4 + %cmp = icmp sgt i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_D_GOT:[0-9+]]], %got(d)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_C_GOT:[0-9+]]], %got(c)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D:[0-9]+]], 0($[[REG_D_GOT]]) +; CHECK-DAG: lw $[[REG_C:[0-9]+]], 0($[[REG_C_GOT]]) +; CHECK: slt $[[REG1:[0-9]+]], $[[REG_D]], $[[REG_C]] +; FIXME: This instruction is redundant. The slt can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 1 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @slt() { +entry: +; CHECK-LABEL: .ent slt + %0 = load i32* @c, align 4 + %1 = load i32* @d, align 4 + %cmp = icmp slt i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_D_GOT:[0-9+]]], %got(d)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_C_GOT:[0-9+]]], %got(c)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D:[0-9]+]], 0($[[REG_D_GOT]]) +; CHECK-DAG: lw $[[REG_C:[0-9]+]], 0($[[REG_C_GOT]]) +; CHECK: slt $[[REG1:[0-9]+]], $[[REG_C]], $[[REG_D]] +; FIXME: This instruction is redundant. The slt can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 1 + store i32 %conv, i32* @b1, align 4 + ret void +} + +; Function Attrs: nounwind +define void @sge() { +entry: +; CHECK-LABEL: .ent sge + %0 = load i32* @c, align 4 + %1 = load i32* @d, align 4 + %cmp = icmp sge i32 %0, %1 + %conv = zext i1 %cmp to i32 + store i32 %conv, i32* @b1, align 4 +; CHECK-DAG: lw $[[REG_D_GOT:[0-9+]]], %got(d)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_C_GOT:[0-9+]]], %got(c)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D:[0-9]+]], 0($[[REG_D_GOT]]) +; CHECK-DAG: lw $[[REG_C:[0-9]+]], 0($[[REG_C_GOT]]) +; CHECK: slt $[[REG1:[0-9]+]], $[[REG_C]], $[[REG_D]] +; CHECK: xori $[[REG2:[0-9]+]], $[[REG1]], 1 +; FIXME: This instruction is redundant. The slt can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG2]], 1 + ret void +} + +; Function Attrs: nounwind +define void @sle() { +entry: +; CHECK-LABEL: .ent sle + %0 = load i32* @c, align 4 + %1 = load i32* @d, align 4 + %cmp = icmp sle i32 %0, %1 + %conv = zext i1 %cmp to i32 +; CHECK-DAG: lw $[[REG_D_GOT:[0-9+]]], %got(d)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_C_GOT:[0-9+]]], %got(c)(${{[0-9]+}}) +; CHECK-DAG: lw $[[REG_D:[0-9]+]], 0($[[REG_D_GOT]]) +; CHECK-DAG: lw $[[REG_C:[0-9]+]], 0($[[REG_C_GOT]]) +; CHECK: slt $[[REG1:[0-9]+]], $[[REG_D]], $[[REG_C]] +; CHECK: xori $[[REG2:[0-9]+]], $[[REG1]], 1 +; FIXME: This instruction is redundant. The slt can only produce 0 and 1. +; CHECK: andi ${{[0-9]+}}, $[[REG2]], 1 + store i32 %conv, i32* @b1, align 4 + ret void +} diff --git a/test/CodeGen/Mips/Fast-ISel/loadstore2.ll b/test/CodeGen/Mips/Fast-ISel/loadstore2.ll index f113a0e..d84478b 100644 --- a/test/CodeGen/Mips/Fast-ISel/loadstore2.ll +++ b/test/CodeGen/Mips/Fast-ISel/loadstore2.ll @@ -6,6 +6,8 @@ target triple = "mips--linux-gnu" @c1 = common global i8 0, align 1 ; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ ; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s @s2 = common global i16 0, align 2 @s1 = common global i16 0, align 2 diff --git a/test/CodeGen/Mips/Fast-ISel/loadstoreconv.ll b/test/CodeGen/Mips/Fast-ISel/loadstoreconv.ll new file mode 100644 index 0000000..f7f2c64 --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/loadstoreconv.ll @@ -0,0 +1,179 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32r2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32 + +@b2 = global i8 0, align 1 +@b1 = global i8 1, align 1 +@uc1 = global i8 0, align 1 +@uc2 = global i8 -1, align 1 +@sc1 = global i8 -128, align 1 +@sc2 = global i8 127, align 1 +@ss1 = global i16 -32768, align 2 +@ss2 = global i16 32767, align 2 +@us1 = global i16 0, align 2 +@us2 = global i16 -1, align 2 +@ssi = global i16 0, align 2 +@ssj = global i16 0, align 2 +@i = global i32 0, align 4 +@j = global i32 0, align 4 +@.str = private unnamed_addr constant [4 x i8] c"%i\0A\00", align 1 +@.str1 = private unnamed_addr constant [7 x i8] c"%i %i\0A\00", align 1 + +; Function Attrs: nounwind +define void @_Z3b_iv() { +entry: +; CHECK-LABEL: .ent _Z3b_iv + %0 = load i8* @b1, align 1 + %tobool = trunc i8 %0 to i1 + %frombool = zext i1 %tobool to i8 + store i8 %frombool, i8* @b2, align 1 + %1 = load i8* @b2, align 1 + %tobool1 = trunc i8 %1 to i1 + %conv = zext i1 %tobool1 to i32 + store i32 %conv, i32* @i, align 4 +; CHECK: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; CHECK: andi $[[REG2:[0-9]+]], $[[REG1]], 1 +; CHECK: sb $[[REG2]], 0(${{[0-9]+}}) + + + + ret void +; CHECK: .end _Z3b_iv +} + +; Function Attrs: nounwind +define void @_Z4uc_iv() { +entry: +; CHECK-LABEL: .ent _Z4uc_iv + + %0 = load i8* @uc1, align 1 + %conv = zext i8 %0 to i32 + store i32 %conv, i32* @i, align 4 + %1 = load i8* @uc2, align 1 + %conv1 = zext i8 %1 to i32 +; CHECK: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 255 + + store i32 %conv1, i32* @j, align 4 + ret void +; CHECK: .end _Z4uc_iv + +} + +; Function Attrs: nounwind +define void @_Z4sc_iv() { +entry: +; mips32r2-LABEL: .ent _Z4sc_iv +; mips32-LABEL: .ent _Z4sc_iv + + %0 = load i8* @sc1, align 1 + %conv = sext i8 %0 to i32 + store i32 %conv, i32* @i, align 4 + %1 = load i8* @sc2, align 1 + %conv1 = sext i8 %1 to i32 + store i32 %conv1, i32* @j, align 4 +; mips32r2: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; mips32r2: seb ${{[0-9]+}}, $[[REG1]] +; mips32: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; mips32: sll $[[REG2:[0-9]+]], $[[REG1]], 24 +; mips32: sra ${{[0-9]+}}, $[[REG2]], 24 + + ret void +; CHECK: .end _Z4sc_iv +} + +; Function Attrs: nounwind +define void @_Z4us_iv() { +entry: +; CHECK-LABEL: .ent _Z4us_iv + %0 = load i16* @us1, align 2 + %conv = zext i16 %0 to i32 + store i32 %conv, i32* @i, align 4 + %1 = load i16* @us2, align 2 + %conv1 = zext i16 %1 to i32 + store i32 %conv1, i32* @j, align 4 + ret void +; CHECK: lhu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 65535 +; CHECK: .end _Z4us_iv +} + +; Function Attrs: nounwind +define void @_Z4ss_iv() { +entry: +; mips32r2-LABEL: .ent _Z4ss_iv +; mips32=LABEL: .ent _Z4ss_iv + + %0 = load i16* @ss1, align 2 + %conv = sext i16 %0 to i32 + store i32 %conv, i32* @i, align 4 + %1 = load i16* @ss2, align 2 + %conv1 = sext i16 %1 to i32 + store i32 %conv1, i32* @j, align 4 +; mips32r2: lhu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; mips32r2: seh ${{[0-9]+}}, $[[REG1]] +; mips32: lhu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; mips32: sll $[[REG2:[0-9]+]], $[[REG1]], 16 +; mips32: sra ${{[0-9]+}}, $[[REG2]], 16 + + ret void +; CHECK: .end _Z4ss_iv +} + +; Function Attrs: nounwind +define void @_Z4b_ssv() { +entry: +; CHECK-LABEL: .ent _Z4b_ssv + %0 = load i8* @b2, align 1 + %tobool = trunc i8 %0 to i1 + %conv = zext i1 %tobool to i16 + store i16 %conv, i16* @ssi, align 2 + ret void +; CHECK: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 1 +; CHECK: .end _Z4b_ssv +} + +; Function Attrs: nounwind +define void @_Z5uc_ssv() { +entry: +; CHECK-LABEL: .ent _Z5uc_ssv + %0 = load i8* @uc1, align 1 + %conv = zext i8 %0 to i16 + store i16 %conv, i16* @ssi, align 2 + %1 = load i8* @uc2, align 1 + %conv1 = zext i8 %1 to i16 +; CHECK: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; CHECK: andi ${{[0-9]+}}, $[[REG1]], 255 + + store i16 %conv1, i16* @ssj, align 2 + ret void +; CHECK: .end _Z5uc_ssv +} + +; Function Attrs: nounwind +define void @_Z5sc_ssv() { +entry: +; mips32r2-LABEL: .ent _Z5sc_ssv +; mips32-LABEL: .ent _Z5sc_ssv + %0 = load i8* @sc1, align 1 + %conv = sext i8 %0 to i16 + store i16 %conv, i16* @ssi, align 2 + %1 = load i8* @sc2, align 1 + %conv1 = sext i8 %1 to i16 + store i16 %conv1, i16* @ssj, align 2 +; mips32r2: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; mips32r2: seb ${{[0-9]+}}, $[[REG1]] +; mips32: lbu $[[REG1:[0-9]+]], 0(${{[0-9]+}}) +; mips32: sll $[[REG2:[0-9]+]], $[[REG1]], 24 +; mips32: sra ${{[0-9]+}}, $[[REG2]], 24 + + ret void +; CHECK: .end _Z5sc_ssv +} + diff --git a/test/CodeGen/Mips/Fast-ISel/loadstrconst.ll b/test/CodeGen/Mips/Fast-ISel/loadstrconst.ll new file mode 100644 index 0000000..93cf4c1 --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/loadstrconst.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@s = common global i8* null, align 4 + +; Function Attrs: nounwind +define void @foo() #0 { +entry: + store i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i8** @s, align 4 + ret void +; CHECK: .ent foo +; CHECK: lw $[[REG1:[0-9]+]], %got($.str)(${{[0-9]+}}) +; CHECK: addiu ${{[0-9]+}}, $[[REG1]], %lo($.str) + +} + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + diff --git a/test/CodeGen/Mips/Fast-ISel/nullvoid.ll b/test/CodeGen/Mips/Fast-ISel/nullvoid.ll index eeaff87..c847561 100644 --- a/test/CodeGen/Mips/Fast-ISel/nullvoid.ll +++ b/test/CodeGen/Mips/Fast-ISel/nullvoid.ll @@ -1,5 +1,7 @@ ; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ ; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s ; Function Attrs: nounwind define void @foo() { diff --git a/test/CodeGen/Mips/Fast-ISel/shift.ll b/test/CodeGen/Mips/Fast-ISel/shift.ll new file mode 100644 index 0000000..18fd5ac --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/shift.ll @@ -0,0 +1,24 @@ +; RUN: llc -march=mipsel -mcpu=mips32r2 -O1 -fast-isel=true -mips-fast-isel -filetype=obj %s -o - \ +; RUN: | llvm-objdump -arch mipsel -mcpu=mips32r2 -d - | FileCheck %s + +; This test checks that encoding for srl is correct when fast-isel for mips32r2 is used. + +%struct.s = type { [4 x i8], i32 } + +define i32 @main() nounwind uwtable { +entry: + %foo = alloca %struct.s, align 4 + %0 = bitcast %struct.s* %foo to i32* + %bf.load = load i32* %0, align 4 + %bf.lshr = lshr i32 %bf.load, 2 + %cmp = icmp ne i32 %bf.lshr, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: + unreachable + +if.end: + ret i32 0 +} + +; CHECK: srl ${{[0-9]+}}, ${{[0-9]+}}, {{[0-9]+}} diff --git a/test/CodeGen/Mips/Fast-ISel/simplestore.ll b/test/CodeGen/Mips/Fast-ISel/simplestore.ll index 5d52481..83e3f3f 100644 --- a/test/CodeGen/Mips/Fast-ISel/simplestore.ll +++ b/test/CodeGen/Mips/Fast-ISel/simplestore.ll @@ -1,5 +1,7 @@ ; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ ; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s @abcd = external global i32 diff --git a/test/CodeGen/Mips/Fast-ISel/simplestorefp1.ll b/test/CodeGen/Mips/Fast-ISel/simplestorefp1.ll index 6759c01..74723ae 100644 --- a/test/CodeGen/Mips/Fast-ISel/simplestorefp1.ll +++ b/test/CodeGen/Mips/Fast-ISel/simplestorefp1.ll @@ -1,5 +1,11 @@ ; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ ; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32r2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32 @f = common global float 0.000000e+00, align 4 @de = common global double 0.000000e+00, align 8 @@ -23,15 +29,25 @@ entry: define void @d1() #0 { entry: store double 1.234567e+00, double* @de, align 8 -; CHECK: .ent d1 -; CHECK: lui $[[REG1a:[0-9]+]], 16371 -; CHECK: ori $[[REG2a:[0-9]+]], $[[REG1a]], 49353 -; CHECK: lui $[[REG1b:[0-9]+]], 21403 -; CHECK: ori $[[REG2b:[0-9]+]], $[[REG1b]], 34951 -; CHECK: mtc1 $[[REG2b]], $f[[REG3:[0-9]+]] -; CHECK: mthc1 $[[REG2a]], $f[[REG3]] -; CHECK: sdc1 $f[[REG3]], 0(${{[0-9]+}}) -; CHECK: .end d1 +; mip32r2: .ent d1 +; mips32r2: lui $[[REG1a:[0-9]+]], 16371 +; mips32r2: ori $[[REG2a:[0-9]+]], $[[REG1a]], 49353 +; mips32r2: lui $[[REG1b:[0-9]+]], 21403 +; mips32r2: ori $[[REG2b:[0-9]+]], $[[REG1b]], 34951 +; mips32r2: mtc1 $[[REG2b]], $f[[REG3:[0-9]+]] +; mips32r2: mthc1 $[[REG2a]], $f[[REG3]] +; mips32r2: sdc1 $f[[REG3]], 0(${{[0-9]+}}) +; mips32r2: .end d1 +; mips32: .ent d1 +; mips32: lui $[[REG1a:[0-9]+]], 16371 +; mips32: ori $[[REG2a:[0-9]+]], $[[REG1a]], 49353 +; mips32: lui $[[REG1b:[0-9]+]], 21403 +; mips32: ori $[[REG2b:[0-9]+]], $[[REG1b]], 34951 +; mips32: mtc1 $[[REG2b]], $f[[REG3:[0-9]+]] +; mips32: mtc1 $[[REG2a]], $f{{[0-9]+}} +; mips32: sdc1 $f[[REG3]], 0(${{[0-9]+}}) +; mips32: .end d1 + ret void } diff --git a/test/CodeGen/Mips/Fast-ISel/simplestorei.ll b/test/CodeGen/Mips/Fast-ISel/simplestorei.ll index 7d2c8e7..128e1de 100644 --- a/test/CodeGen/Mips/Fast-ISel/simplestorei.ll +++ b/test/CodeGen/Mips/Fast-ISel/simplestorei.ll @@ -1,5 +1,7 @@ ; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ ; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s @ijk = external global i32 diff --git a/test/CodeGen/Mips/abicalls.ll b/test/CodeGen/Mips/abicalls.ll index 6fa33aa..7edc3e2 100644 --- a/test/CodeGen/Mips/abicalls.ll +++ b/test/CodeGen/Mips/abicalls.ll @@ -1,16 +1,11 @@ -; -; When the assembler is ready a .s file for it will -; be created. +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -relocation-model=static %s -o - | FileCheck -check-prefix=ABICALLS -check-prefix=STATIC %s +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 %s -o - | FileCheck -check-prefix=ABICALLS -check-prefix=PIC %s +; RUN: llc -filetype=asm -mtriple mips64el-unknown-linux -mcpu=mips4 -relocation-model=static %s -o - | FileCheck -check-prefix=ABICALLS -check-prefix=PIC %s +; RUN: llc -filetype=asm -mtriple mips64el-unknown-linux -mcpu=mips64 -relocation-model=static %s -o - | FileCheck -check-prefix=ABICALLS -check-prefix=PIC %s -; Note that EF_MIPS_CPIC is set by -mabicalls which is the default on Linux -; TODO need to support -mno-abicalls +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -mattr noabicalls -relocation-model=static %s -o - | FileCheck -implicit-check-not='.abicalls' -implicit-check-not='pic0' %s -; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -relocation-model=static %s -o - | FileCheck -check-prefix=CHECK-STATIC %s -; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 %s -o - | FileCheck -check-prefix=CHECK-PIC %s -; RUN: llc -filetype=asm -mtriple mips64el-unknown-linux -mcpu=mips4 -relocation-model=static %s -o - | FileCheck -check-prefix=CHECK-PIC %s -; RUN: llc -filetype=asm -mtriple mips64el-unknown-linux -mcpu=mips64 -relocation-model=static %s -o - | FileCheck -check-prefix=CHECK-PIC %s +; ABICALLS: .abicalls -; CHECK-STATIC: .abicalls -; CHECK-STATIC-NEXT: pic0 -; CHECK-PIC: .abicalls -; CHECK-PIC-NOT: pic0 +; STATIC: pic0 +; PIC-NOT: pic0 diff --git a/test/CodeGen/Mips/abiflags-xx.ll b/test/CodeGen/Mips/abiflags-xx.ll index b8aa071..c461012 100644 --- a/test/CodeGen/Mips/abiflags-xx.ll +++ b/test/CodeGen/Mips/abiflags-xx.ll @@ -1,5 +1,4 @@ ; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -mattr=fpxx %s -o - | FileCheck %s -; XFAIL: * ; CHECK: .nan legacy ; CHECK: .module fp=xx diff --git a/test/CodeGen/Mips/abiflags32.ll b/test/CodeGen/Mips/abiflags32.ll index 093964f..e32d4a5 100644 --- a/test/CodeGen/Mips/abiflags32.ll +++ b/test/CodeGen/Mips/abiflags32.ll @@ -3,10 +3,15 @@ ; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips64 -mattr=-n64,n32 %s -o - | FileCheck -check-prefix=CHECK-64n %s ; CHECK: .nan legacy -; CHECK: .module fp=32 +; We don't emit '.module fp=32' for compatibility with binutils 2.24 which +; doesn't accept .module. +; CHECK-NOT: .module fp=32 ; CHECK-64: .nan legacy +; We do emit '.module fp=64' though since it contradicts the default value. ; CHECK-64: .module fp=64 ; CHECK-64n: .nan legacy -; CHECK-64n: .module fp=64 +; We don't emit '.module fp=64' for compatibility with binutils 2.24 which +; doesn't accept .module. +; CHECK-64n-NOT: .module fp=64 diff --git a/test/CodeGen/Mips/atomic.ll b/test/CodeGen/Mips/atomic.ll index 066d42c..78fd829 100644 --- a/test/CodeGen/Mips/atomic.ll +++ b/test/CodeGen/Mips/atomic.ll @@ -8,11 +8,11 @@ ; Keep one big-endian check so that we don't reduce testing, but don't add more ; since endianness doesn't affect the body of the atomic operations. -; RUN: llc -march=mips --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=CHECK-EB +; RUN: llc -march=mips --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EB @x = common global i32 0, align 4 -define i32 @AtomicLoadAdd32(i32 %incr) nounwind { +define i32 @AtomicLoadAdd32(i32 signext %incr) nounwind { entry: %0 = atomicrmw add i32* @x, i32 %incr monotonic ret i32 %0 @@ -29,7 +29,7 @@ entry: ; ALL: beqz $[[R2]], $[[BB0]] } -define i32 @AtomicLoadNand32(i32 %incr) nounwind { +define i32 @AtomicLoadNand32(i32 signext %incr) nounwind { entry: %0 = atomicrmw nand i32* @x, i32 %incr monotonic ret i32 %0 @@ -47,7 +47,7 @@ entry: ; ALL: beqz $[[R2]], $[[BB0]] } -define i32 @AtomicSwap32(i32 %newval) nounwind { +define i32 @AtomicSwap32(i32 signext %newval) nounwind { entry: %newval.addr = alloca i32, align 4 store i32 %newval, i32* %newval.addr, align 4 @@ -66,7 +66,7 @@ entry: ; ALL: beqz $[[R2]], $[[BB0]] } -define i32 @AtomicCmpSwap32(i32 %oldval, i32 %newval) nounwind { +define i32 @AtomicCmpSwap32(i32 signext %oldval, i32 signext %newval) nounwind { entry: %newval.addr = alloca i32, align 4 store i32 %newval, i32* %newval.addr, align 4 @@ -246,6 +246,7 @@ entry: ; NO-SEB-SEH: sra $2, $[[R17]], 24 ; HAS-SEB-SEH: seb $2, $[[R16]] + } define signext i8 @AtomicCmpSwap8(i8 signext %oldval, i8 signext %newval) nounwind { @@ -292,6 +293,49 @@ entry: ; HAS-SEB-SEH: seb $2, $[[R17]] } +define i1 @AtomicCmpSwapRes8(i8* %ptr, i8 signext %oldval, i8 signext %newval) nounwind { +entry: + %0 = cmpxchg i8* %ptr, i8 %oldval, i8 %newval monotonic monotonic + %1 = extractvalue { i8, i1 } %0, 1 + ret i1 %1 +; ALL-LABEL: AtomicCmpSwapRes8 + +; ALL: addiu $[[R1:[0-9]+]], $zero, -4 +; ALL: and $[[R2:[0-9]+]], $4, $[[R1]] +; ALL: andi $[[R3:[0-9]+]], $4, 3 +; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 +; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 3 +; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 +; ALL: ori $[[R6:[0-9]+]], $zero, 255 +; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] +; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] +; ALL: andi $[[R9:[0-9]+]], $5, 255 +; ALL: sllv $[[R10:[0-9]+]], $[[R9]], $[[R5]] +; ALL: andi $[[R11:[0-9]+]], $6, 255 +; ALL: sllv $[[R12:[0-9]+]], $[[R11]], $[[R5]] + +; ALL: $[[BB0:[A-Z_0-9]+]]: +; ALL: ll $[[R13:[0-9]+]], 0($[[R2]]) +; ALL: and $[[R14:[0-9]+]], $[[R13]], $[[R7]] +; ALL: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] + +; ALL: and $[[R15:[0-9]+]], $[[R13]], $[[R8]] +; ALL: or $[[R16:[0-9]+]], $[[R15]], $[[R12]] +; ALL: sc $[[R16]], 0($[[R2]]) +; ALL: beqz $[[R16]], $[[BB0]] + +; ALL: $[[BB1]]: +; ALL: srlv $[[R17:[0-9]+]], $[[R14]], $[[R5]] + +; NO-SEB-SEH: sll $[[R18:[0-9]+]], $[[R17]], 24 +; NO-SEB-SEH: sra $[[R19:[0-9]+]], $[[R18]], 24 + +; HAS-SEB-SEH: seb $[[R19:[0-9]+]], $[[R17]] + +; ALL: xor $[[R20:[0-9]+]], $[[R19]], $5 +; ALL: sltiu $2, $[[R20]], 1 +} + ; Check one i16 so that we cover the seh sign extend @z = common global i16 0, align 1 @@ -337,7 +381,7 @@ entry: @countsint = common global i32 0, align 4 -define i32 @CheckSync(i32 %v) nounwind noinline { +define i32 @CheckSync(i32 signext %v) nounwind noinline { entry: %0 = atomicrmw add i32* @countsint, i32 %v seq_cst ret i32 %0 @@ -371,7 +415,7 @@ entry: ; Check that MIPS32R6 has the correct offset range. ; FIXME: At the moment, we don't seem to do addr+offset for any atomic load/store. -define i32 @AtomicLoadAdd32_OffGt9Bit(i32 %incr) nounwind { +define i32 @AtomicLoadAdd32_OffGt9Bit(i32 signext %incr) nounwind { entry: %0 = atomicrmw add i32* getelementptr(i32* @x, i32 256), i32 %incr monotonic ret i32 %0 diff --git a/test/CodeGen/Mips/bswap.ll b/test/CodeGen/Mips/bswap.ll index 812eef1..f182e65 100644 --- a/test/CodeGen/Mips/bswap.ll +++ b/test/CodeGen/Mips/bswap.ll @@ -2,7 +2,7 @@ ; RUN: llc < %s -march=mips64el -mcpu=mips64r2 | FileCheck %s -check-prefix=MIPS64 ; RUN: llc < %s -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips32r2 -mattr=+mips16 | FileCheck %s -check-prefix=MIPS16 -define i32 @bswap32(i32 %x) nounwind readnone { +define i32 @bswap32(i32 signext %x) nounwind readnone { entry: ; MIPS32-LABEL: bswap32: ; MIPS32: wsbh $[[R0:[0-9]+]] @@ -29,7 +29,7 @@ entry: ret i32 %or.3 } -define i64 @bswap64(i64 %x) nounwind readnone { +define i64 @bswap64(i64 signext %x) nounwind readnone { entry: ; MIPS32-LABEL: bswap64: ; MIPS32: wsbh $[[R0:[0-9]+]] @@ -72,24 +72,24 @@ entry: define <4 x i32> @bswapv4i32(<4 x i32> %x) nounwind readnone { entry: ; MIPS32-LABEL: bswapv4i32: -; MIPS32: wsbh $[[R0:[0-9]+]] -; MIPS32: rotr ${{[0-9]+}}, $[[R0]], 16 -; MIPS32: wsbh $[[R0:[0-9]+]] -; MIPS32: rotr ${{[0-9]+}}, $[[R0]], 16 -; MIPS32: wsbh $[[R0:[0-9]+]] -; MIPS32: rotr ${{[0-9]+}}, $[[R0]], 16 -; MIPS32: wsbh $[[R0:[0-9]+]] -; MIPS32: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS32-DAG: wsbh $[[R0:[0-9]+]] +; MIPS32-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS32-DAG: wsbh $[[R0:[0-9]+]] +; MIPS32-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS32-DAG: wsbh $[[R0:[0-9]+]] +; MIPS32-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS32-DAG: wsbh $[[R0:[0-9]+]] +; MIPS32-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 ; MIPS64-LABEL: bswapv4i32: -; MIPS64: wsbh $[[R0:[0-9]+]] -; MIPS64: rotr ${{[0-9]+}}, $[[R0]], 16 -; MIPS64: wsbh $[[R0:[0-9]+]] -; MIPS64: rotr ${{[0-9]+}}, $[[R0]], 16 -; MIPS64: wsbh $[[R0:[0-9]+]] -; MIPS64: rotr ${{[0-9]+}}, $[[R0]], 16 -; MIPS64: wsbh $[[R0:[0-9]+]] -; MIPS64: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS64-DAG: wsbh $[[R0:[0-9]+]] +; MIPS64-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS64-DAG: wsbh $[[R0:[0-9]+]] +; MIPS64-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS64-DAG: wsbh $[[R0:[0-9]+]] +; MIPS64-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 +; MIPS64-DAG: wsbh $[[R0:[0-9]+]] +; MIPS64-DAG: rotr ${{[0-9]+}}, $[[R0]], 16 ; Don't bother with a MIPS16 version. It's just bswap32 repeated four times and ; would be very long diff --git a/test/CodeGen/Mips/buildpairextractelementf64.ll b/test/CodeGen/Mips/buildpairextractelementf64.ll index 88d1d07..7682a98 100644 --- a/test/CodeGen/Mips/buildpairextractelementf64.ll +++ b/test/CodeGen/Mips/buildpairextractelementf64.ll @@ -1,15 +1,19 @@ -; RUN: llc -march=mipsel < %s | FileCheck %s -check-prefix=FP32 -check-prefix=CHECK -; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=FP32 -check-prefix=CHECK -; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+fp64 < %s | FileCheck %s -check-prefix=FP64 -check-prefix=CHECK -; RUN: llc -march=mips -mcpu=mips32r2 -mattr=+fp64 < %s | FileCheck %s -check-prefix=FP64 -check-prefix=CHECK +; RUN: llc -march=mipsel < %s | FileCheck %s -check-prefix=NO-MFHC1 -check-prefix=ALL +; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=NO-MFHC1 -check-prefix=ALL +; RUN: llc -march=mipsel -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=HAS-MFHC1 -check-prefix=ALL +; RUN: llc -march=mips -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=HAS-MFHC1 -check-prefix=ALL +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+fp64 < %s | FileCheck %s -check-prefix=HAS-MFHC1 -check-prefix=ALL +; RUN: llc -march=mips -mcpu=mips32r2 -mattr=+fp64 < %s | FileCheck %s -check-prefix=HAS-MFHC1 -check-prefix=ALL @a = external global i32 -; CHECK-LABEL: f: -; FP32: mtc1 -; FP32: mtc1 -; FP64-DAG: mtc1 -; FP64-DAG: mthc1 +; ALL-LABEL: f: + +; NO-MFHC1: mtc1 +; NO-MFHC1: mtc1 + +; HAS-MFHC1-DAG: mtc1 +; HAS-MFHC1-DAG: mthc1 define double @f(i32 %a1, double %d) nounwind { entry: @@ -18,11 +22,13 @@ entry: ret double %add } -; CHECK-LABEL: f3: -; FP32: mfc1 -; FP32: mfc1 -; FP64-DAG: mfc1 -; FP64-DAG: mfhc1 +; ALL-LABEL: f3: + +; NO-MFHC1: mfc1 +; NO-MFHC1: mfc1 + +; HAS-MFHC1-DAG: mfc1 +; HAS-MFHC1-DAG: mfhc1 define void @f3(double %d, i32 %a1) nounwind { entry: diff --git a/test/CodeGen/Mips/cconv/arguments-float.ll b/test/CodeGen/Mips/cconv/arguments-float.ll index e2119ec..14a3baa 100644 --- a/test/CodeGen/Mips/cconv/arguments-float.ll +++ b/test/CodeGen/Mips/cconv/arguments-float.ll @@ -69,26 +69,26 @@ entry: ; O32-DAG: sw [[R4]], 28([[R2]]) ; NEW-DAG: sd $6, 24([[R2]]) -; O32-DAG: lw [[R3:\$[0-9]+]], 32($sp) -; O32-DAG: lw [[R4:\$[0-9]+]], 36($sp) +; O32-DAG: lw [[R3:\$([0-9]+|gp)]], 32($sp) +; O32-DAG: lw [[R4:\$([0-9]+|gp)]], 36($sp) ; O32-DAG: sw [[R3]], 32([[R2]]) ; O32-DAG: sw [[R4]], 36([[R2]]) ; NEW-DAG: sd $7, 32([[R2]]) -; O32-DAG: lw [[R3:\$[0-9]+]], 40($sp) -; O32-DAG: lw [[R4:\$[0-9]+]], 44($sp) +; O32-DAG: lw [[R3:\$([0-9]+|gp)]], 40($sp) +; O32-DAG: lw [[R4:\$([0-9]+|gp)]], 44($sp) ; O32-DAG: sw [[R3]], 40([[R2]]) ; O32-DAG: sw [[R4]], 44([[R2]]) ; NEW-DAG: sd $8, 40([[R2]]) -; O32-DAG: lw [[R3:\$[0-9]+]], 48($sp) -; O32-DAG: lw [[R4:\$[0-9]+]], 52($sp) +; O32-DAG: lw [[R3:\$([0-9]+|gp)]], 48($sp) +; O32-DAG: lw [[R4:\$([0-9]+|gp)]], 52($sp) ; O32-DAG: sw [[R3]], 48([[R2]]) ; O32-DAG: sw [[R4]], 52([[R2]]) ; NEW-DAG: sd $9, 48([[R2]]) -; O32-DAG: lw [[R3:\$[0-9]+]], 56($sp) -; O32-DAG: lw [[R4:\$[0-9]+]], 60($sp) +; O32-DAG: lw [[R3:\$([0-9]+|gp)]], 56($sp) +; O32-DAG: lw [[R4:\$([0-9]+|gp)]], 60($sp) ; O32-DAG: sw [[R3]], 56([[R2]]) ; O32-DAG: sw [[R4]], 60([[R2]]) ; NEW-DAG: sd $10, 56([[R2]]) @@ -135,8 +135,8 @@ entry: ; SYM64-DAG: ld [[R2:\$[0-9]]], %got_disp(floats)( ; The first four arguments are the same in O32/N32/N64. -; The first argument isn't floating point so floating point registers are not -; used. +; The first argument is floating point but soft-float is enabled so floating +; point registers are not used. ; MD00305 and GCC disagree on this one. MD00305 says that floats are treated ; as 8-byte aligned and occupy two slots on O32. GCC is treating them as 4-byte ; aligned and occupying one slot. We'll use GCC's definition. @@ -195,7 +195,7 @@ entry: ; O32-DAG: sw $7, 12([[R2]]) ; NEW-DAG: sd $5, 8([[R2]]) -define void @float_arg2(i8 %a, float %b) nounwind { +define void @float_arg2(i8 signext %a, float %b) nounwind { entry: %0 = getelementptr [11 x i8]* @bytes, i32 0, i32 1 store volatile i8 %a, i8* %0 diff --git a/test/CodeGen/Mips/cconv/arguments-hard-float-varargs.ll b/test/CodeGen/Mips/cconv/arguments-hard-float-varargs.ll index aadf7d1..70ccf14 100644 --- a/test/CodeGen/Mips/cconv/arguments-hard-float-varargs.ll +++ b/test/CodeGen/Mips/cconv/arguments-hard-float-varargs.ll @@ -4,11 +4,11 @@ ; RUN-TODO: llc -march=mips64 -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 %s ; RUN-TODO: llc -march=mips64el -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 %s -; RUN: llc -march=mips64 -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=N32 --check-prefix=NEW %s -; RUN: llc -march=mips64el -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=N32 --check-prefix=NEW %s +; RUN: llc -march=mips64 -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=N32 --check-prefix=NEW --check-prefix=NEWBE %s +; RUN: llc -march=mips64el -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=N32 --check-prefix=NEW --check-prefix=NEWLE %s -; RUN: llc -march=mips64 -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM64 --check-prefix=N64 --check-prefix=NEW %s -; RUN: llc -march=mips64el -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM64 --check-prefix=N64 --check-prefix=NEW %s +; RUN: llc -march=mips64 -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM64 --check-prefix=N64 --check-prefix=NEW --check-prefix=NEWBE %s +; RUN: llc -march=mips64el -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM64 --check-prefix=N64 --check-prefix=NEW --check-prefix=NEWLE %s ; Test the effect of varargs on floating point types in the non-variable part ; of the argument list as specified by section 2 of the MIPSpro N32 Handbook. @@ -34,6 +34,7 @@ entry: %b = va_arg i8** %ap, double %1 = getelementptr [11 x double]* @doubles, i32 0, i32 2 store volatile double %b, double* %1 + call void @llvm.va_end(i8* %ap2) ret void } @@ -98,6 +99,7 @@ entry: %b = va_arg i8** %ap, float %1 = getelementptr [11 x float]* @floats, i32 0, i32 2 store volatile float %b, float* %1 + call void @llvm.va_end(i8* %ap2) ret void } @@ -140,16 +142,18 @@ entry: ; Increment the pointer then get the varargs arg ; LLVM will rebind the load to the stack pointer instead of the varargs pointer ; during lowering. This is fine and doesn't change the behaviour. -; N32/N64 is using ori instead of addiu/daddiu but (although odd) this is fine -; since the stack is always aligned. +; Also, in big-endian mode the offset must be increased by 4 to retrieve the +; correct half of the argument slot. +; ; O32-DAG: addiu [[VAPTR]], [[VAPTR]], 4 ; O32-DAG: sw [[VAPTR]], 4($sp) -; N32-DAG: ori [[VAPTR]], [[VAPTR]], 4 +; N32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 ; N32-DAG: sw [[VAPTR]], 4($sp) -; N64-DAG: ori [[VAPTR]], [[VAPTR]], 4 +; N64-DAG: daddiu [[VAPTR]], [[VAPTR]], 8 ; N64-DAG: sd [[VAPTR]], 0($sp) ; O32-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 12($sp) -; NEW-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 8($sp) +; NEWLE-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 8($sp) +; NEWBE-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 12($sp) ; ALL-DAG: swc1 [[FTMP1]], 8([[R2]]) declare void @llvm.va_start(i8*) diff --git a/test/CodeGen/Mips/cconv/arguments-varargs.ll b/test/CodeGen/Mips/cconv/arguments-varargs.ll new file mode 100644 index 0000000..adacda5 --- /dev/null +++ b/test/CodeGen/Mips/cconv/arguments-varargs.ll @@ -0,0 +1,1104 @@ +; RUN: llc -mtriple=mips-linux -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-BE %s +; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-LE %s + +; RUN-TODO: llc -march=mips64 -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s +; RUN-TODO: llc -march=mips64el -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s + +; RUN: llc -mtriple=mips64-linux -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N32 --check-prefix=NEW-BE %s +; RUN: llc -mtriple=mips64el-linux -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N32 --check-prefix=NEW-LE %s + +; RUN: llc -march=mips64 -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N64 --check-prefix=NEW-BE %s +; RUN: llc -march=mips64el -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N64 --check-prefix=NEW-LE %s + +@hwords = global [3 x i16] zeroinitializer, align 1 +@words = global [3 x i32] zeroinitializer, align 1 +@dwords = global [3 x i64] zeroinitializer, align 1 + +define void @fn_i16_dotdotdot_i16(i16 %a, ...) { +entry: +; ALL-LABEL: fn_i16_dotdotdot_i16: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) +; O32-DAG: sw $5, 12([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 12 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first +; fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) + +; Copy the arg to the global +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) + +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( + +; ALL-DAG: sh [[ARG1]], 2([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) + +; Copy the arg to the global +; ALL-DAG: sh [[ARG2]], 4([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i16 + %e1 = getelementptr [3 x i16]* @hwords, i32 0, i32 1 + store volatile i16 %arg1, i16* %e1, align 2 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i16 + %e2 = getelementptr [3 x i16]* @hwords, i32 0, i32 2 + store volatile i16 %arg2, i16* %e2, align 2 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i16_dotdotdot_i32(i16 %a, ...) { +entry: +; ALL-LABEL: fn_i16_dotdotdot_i32: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) +; O32-DAG: sw $5, 12([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 12 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first +; fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) + +; Copy the arg to the global +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) + +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( + +; ALL-DAG: sw [[ARG1]], 4([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) + +; Copy the arg to the global +; ALL-DAG: sw [[ARG2]], 8([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i32 + %e1 = getelementptr [3 x i32]* @words, i32 0, i32 1 + store volatile i32 %arg1, i32* %e1, align 4 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i32 + %e2 = getelementptr [3 x i32]* @words, i32 0, i32 2 + store volatile i32 %arg2, i32* %e2, align 4 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i16_dotdotdot_i64(i16 %a, ...) { +entry: +; ALL-LABEL: fn_i16_dotdotdot_i64: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) +; O32-DAG: sw $5, 12([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 12 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first +; fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] (and realign pointer for O32) +; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 +; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 +; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] +; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion and copy it to the global. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG1]], 8([[GV]]) +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG1]], 12([[GV]]) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( +; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-DAG: sd [[ARG1]], 8([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. +; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 +; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] +; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion and copy it to the global. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG2]], 16([[GV]]) +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG2]], 20([[GV]]) + +; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-DAG: sd [[ARG2]], 16([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i64 + %e1 = getelementptr [3 x i64]* @dwords, i32 0, i32 1 + store volatile i64 %arg1, i64* %e1, align 8 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i64 + %e2 = getelementptr [3 x i64]* @dwords, i32 0, i32 2 + store volatile i64 %arg2, i64* %e2, align 8 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i32_dotdotdot_i16(i32 %a, ...) { +entry: +; ALL-LABEL: fn_i32_dotdotdot_i16: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) +; O32-DAG: sw $5, 12([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 12 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first +; fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) + +; Copy the arg to the global +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) + +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( + +; ALL-DAG: sh [[ARG1]], 2([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) + +; Copy the arg to the global +; ALL-DAG: sh [[ARG2]], 4([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i16 + %e1 = getelementptr [3 x i16]* @hwords, i32 0, i32 1 + store volatile i16 %arg1, i16* %e1, align 2 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i16 + %e2 = getelementptr [3 x i16]* @hwords, i32 0, i32 2 + store volatile i16 %arg2, i16* %e2, align 2 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i32_dotdotdot_i32(i32 %a, ...) { +entry: +; ALL-LABEL: fn_i32_dotdotdot_i32: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) +; O32-DAG: sw $5, 12([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 12 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first +; fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) + +; Copy the arg to the global +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) + +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( + +; ALL-DAG: sw [[ARG1]], 4([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) + +; Copy the arg to the global +; ALL-DAG: sw [[ARG2]], 8([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i32 + %e1 = getelementptr [3 x i32]* @words, i32 0, i32 1 + store volatile i32 %arg1, i32* %e1, align 4 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i32 + %e2 = getelementptr [3 x i32]* @words, i32 0, i32 2 + store volatile i32 %arg2, i32* %e2, align 4 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i32_dotdotdot_i64(i32 %a, ...) { +entry: +; ALL-LABEL: fn_i32_dotdotdot_i64: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) +; O32-DAG: sw $5, 12([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 12 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first +; fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] (and realign pointer for O32) +; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 +; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 +; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] +; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion and copy it to the global. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG1]], 8([[GV]]) +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG1]], 12([[GV]]) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( +; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-DAG: sd [[ARG1]], 8([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. +; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 +; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] +; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion and copy it to the global. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG2]], 16([[GV]]) +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG2]], 20([[GV]]) + +; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-DAG: sd [[ARG2]], 16([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i64 + %e1 = getelementptr [3 x i64]* @dwords, i32 0, i32 1 + store volatile i64 %arg1, i64* %e1, align 8 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i64 + %e2 = getelementptr [3 x i64]* @dwords, i32 0, i32 2 + store volatile i64 %arg2, i64* %e2, align 8 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i64_dotdotdot_i16(i64 %a, ...) { +entry: +; ALL-LABEL: fn_i64_dotdotdot_i16: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 16 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the +; first fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) + +; Copy the arg to the global +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) + +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( + +; ALL-DAG: sh [[ARG1]], 2([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) + +; Copy the arg to the global +; ALL-DAG: sh [[ARG2]], 4([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i16 + %e1 = getelementptr [3 x i16]* @hwords, i32 0, i32 1 + store volatile i16 %arg1, i16* %e1, align 2 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i16 + %e2 = getelementptr [3 x i16]* @hwords, i32 0, i32 2 + store volatile i16 %arg2, i16* %e2, align 2 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i64_dotdotdot_i32(i64 %a, ...) { +entry: +; ALL-LABEL: fn_i64_dotdotdot_i32: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 16 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the +; first fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) + +; Copy the arg to the global +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) + +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( + +; ALL-DAG: sw [[ARG1]], 4([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) + +; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) + +; Copy the arg to the global +; ALL-DAG: sw [[ARG2]], 8([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i32 + %e1 = getelementptr [3 x i32]* @words, i32 0, i32 1 + store volatile i32 %arg1, i32* %e1, align 4 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i32 + %e2 = getelementptr [3 x i32]* @words, i32 0, i32 2 + store volatile i32 %arg2, i32* %e2, align 4 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +define void @fn_i64_dotdotdot_i64(i64 %a, ...) { +entry: +; ALL-LABEL: fn_i64_dotdotdot_i64: + +; Set up the stack with an 8-byte local area. N32/N64 must also make room for +; the argument save area (56 bytes). +; O32: addiu [[SP:\$sp]], $sp, -8 +; N32: addiu [[SP:\$sp]], $sp, -64 +; N64: daddiu [[SP:\$sp]], $sp, -64 + +; Save variable argument portion on the stack +; O32-DAG: sw $7, 20([[SP]]) +; O32-DAG: sw $6, 16([[SP]]) + +; NEW-DAG: sd $11, 56([[SP]]) +; NEW-DAG: sd $10, 48([[SP]]) +; NEW-DAG: sd $9, 40([[SP]]) +; NEW-DAG: sd $8, 32([[SP]]) +; NEW-DAG: sd $7, 24([[SP]]) +; NEW-DAG: sd $6, 16([[SP]]) +; NEW-DAG: sd $5, 8([[SP]]) + +; Initialize variable argument pointer. +; For O32, the offset is 16 due to the 4 bytes used to store local variables, +; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the +; first fixed argument. +; For N32/N64, it is only 8 since the fixed arguments do not reserve stack +; space. +; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 +; O32-DAG: sw [[VA]], 0([[SP]]) + +; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 +; N32-DAG: sw [[VA]], 0([[SP]]) + +; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 +; N64-DAG: sd [[VA]], 0([[SP]]) + +; Store [[VA]] +; O32-DAG: sw [[VA]], 0([[SP]]) + +; ALL: # ANCHOR1 + +; Increment [[VA]] (and realign pointer for O32) +; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 +; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 +; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] +; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N32-DAG: sw [[VA2]], 0([[SP]]) + +; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) +; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 +; N64-DAG: sd [[VA2]], 0([[SP]]) + +; Load the first argument from the variable portion and copy it to the global. +; This has used the stack pointer directly rather than the [[VA]] we just set +; up. +; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte +; order. +; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG1]], 8([[GV]]) +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) +; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG1]], 12([[GV]]) + +; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) +; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( +; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) +; NEW-DAG: sd [[ARG1]], 8([[GV]]) + +; ALL: # ANCHOR2 + +; Increment [[VA]] again. +; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. +; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 +; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] +; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) + +; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) +; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N32-DAG: sw [[VA3]], 0([[SP]]) + +; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) +; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 +; N64-DAG: sd [[VA3]], 0([[SP]]) + +; Load the second argument from the variable portion and copy it to the global. +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG2]], 16([[GV]]) +; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) +; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 +; O32-DAG: sw [[VA2]], 0([[SP]]) +; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) +; O32-DAG: sw [[ARG2]], 20([[GV]]) + +; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) +; NEW-DAG: sd [[ARG2]], 16([[GV]]) + + %ap = alloca i8*, align 8 + %ap2 = bitcast i8** %ap to i8* + call void @llvm.va_start(i8* %ap2) + + call void asm sideeffect "# ANCHOR1", ""() + %arg1 = va_arg i8** %ap, i64 + %e1 = getelementptr [3 x i64]* @dwords, i32 0, i32 1 + store volatile i64 %arg1, i64* %e1, align 8 + + call void asm sideeffect "# ANCHOR2", ""() + %arg2 = va_arg i8** %ap, i64 + %e2 = getelementptr [3 x i64]* @dwords, i32 0, i32 2 + store volatile i64 %arg2, i64* %e2, align 8 + + call void @llvm.va_end(i8* %ap2) + + ret void +} + +declare void @llvm.va_start(i8*) +declare void @llvm.va_end(i8*) diff --git a/test/CodeGen/Mips/cconv/arguments.ll b/test/CodeGen/Mips/cconv/arguments.ll index 8fe29f3..43da604 100644 --- a/test/CodeGen/Mips/cconv/arguments.ll +++ b/test/CodeGen/Mips/cconv/arguments.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=mips -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 --check-prefix=O32BE %s -; RUN: llc -march=mipsel -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 --check-prefix=O32LE %s +; RUN: llc -march=mips -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 %s +; RUN: llc -march=mipsel -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 %s ; RUN-TODO: llc -march=mips64 -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 %s ; RUN-TODO: llc -march=mips64el -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=SYM32 --check-prefix=O32 %s @@ -23,8 +23,10 @@ @floats = global [11 x float] zeroinitializer @doubles = global [11 x double] zeroinitializer -define void @align_to_arg_slots(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f, i8 %g, - i8 %h, i8 %i, i8 %j) nounwind { +define void @align_to_arg_slots(i8 signext %a, i8 signext %b, i8 signext %c, + i8 signext %d, i8 signext %e, i8 signext %f, + i8 signext %g, i8 signext %h, i8 signext %i, + i8 signext %j) nounwind { entry: %0 = getelementptr [11 x i8]* @bytes, i32 0, i32 1 store volatile i8 %a, i8* %0 @@ -53,7 +55,7 @@ entry: ; We won't test the way the global address is calculated in this test. This is ; just to get the register number for the other checks. ; SYM32-DAG: addiu [[R1:\$[0-9]+]], ${{[0-9]+}}, %lo(bytes) -; SYM64-DAG: ld [[R1:\$[0-9]]], %got_disp(bytes)( +; SYM64-DAG: ld [[R1:\$[0-9]+]], %got_disp(bytes)( ; The first four arguments are the same in O32/N32/N64 ; ALL-DAG: sb $4, 1([[R1]]) @@ -82,15 +84,16 @@ entry: ; increase by 4 for O32 and 8 for N32/N64. ; O32-DAG: lw [[R3:\$[0-9]+]], 32($sp) ; O32-DAG: sb [[R3]], 9([[R1]]) -; NEW-DAG: lw [[R3:\$[0-9]+]], 0($sp) +; NEW-DAG: ld [[R3:\$[0-9]+]], 0($sp) ; NEW-DAG: sb [[R3]], 9([[R1]]) ; O32-DAG: lw [[R3:\$[0-9]+]], 36($sp) ; O32-DAG: sb [[R3]], 10([[R1]]) -; NEW-DAG: lw [[R3:\$[0-9]+]], 8($sp) +; NEW-DAG: ld [[R3:\$[0-9]+]], 8($sp) ; NEW-DAG: sb [[R3]], 10([[R1]]) -define void @slot_skipping(i8 %a, i64 %b, i8 %c, i8 %d, - i8 %e, i8 %f, i8 %g, i64 %i, i8 %j) nounwind { +define void @slot_skipping(i8 signext %a, i64 signext %b, i8 signext %c, + i8 signext %d, i8 signext %e, i8 signext %f, + i8 signext %g, i64 signext %i, i8 signext %j) nounwind { entry: %0 = getelementptr [11 x i8]* @bytes, i32 0, i32 1 store volatile i8 %a, i8* %0 @@ -117,9 +120,9 @@ entry: ; We won't test the way the global address is calculated in this test. This is ; just to get the register number for the other checks. ; SYM32-DAG: addiu [[R1:\$[0-9]+]], ${{[0-9]+}}, %lo(bytes) -; SYM64-DAG: ld [[R1:\$[0-9]]], %got_disp(bytes)( +; SYM64-DAG: ld [[R1:\$[0-9]+]], %got_disp(bytes)( ; SYM32-DAG: addiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) -; SYM64-DAG: ld [[R2:\$[0-9]]], %got_disp(dwords)( +; SYM64-DAG: ld [[R2:\$[0-9]+]], %got_disp(dwords)( ; The first argument is the same in O32/N32/N64. ; ALL-DAG: sb $4, 1([[R1]]) @@ -137,8 +140,7 @@ entry: ; It's not clear why O32 uses lbu for this argument, but it's not wrong so we'll ; accept it for now. The only IR difference is that this argument has ; anyext from i8 and align 8 on it. -; O32LE-DAG: lbu [[R3:\$[0-9]+]], 16($sp) -; O32BE-DAG: lbu [[R3:\$[0-9]+]], 19($sp) +; O32-DAG: lw [[R3:\$[0-9]+]], 16($sp) ; O32-DAG: sb [[R3]], 2([[R1]]) ; NEW-DAG: sb $6, 2([[R1]]) ; O32-DAG: lw [[R3:\$[0-9]+]], 20($sp) @@ -166,5 +168,5 @@ entry: ; increase by 4 for O32 and 8 for N32/N64. ; O32-DAG: lw [[R3:\$[0-9]+]], 48($sp) ; O32-DAG: sb [[R3]], 7([[R1]]) -; NEW-DAG: lw [[R3:\$[0-9]+]], 0($sp) +; NEW-DAG: ld [[R3:\$[0-9]+]], 0($sp) ; NEW-DAG: sb [[R3]], 7([[R1]]) diff --git a/test/CodeGen/Mips/cconv/return-float.ll b/test/CodeGen/Mips/cconv/return-float.ll index 28cf83d..d1a5e4f 100644 --- a/test/CodeGen/Mips/cconv/return-float.ll +++ b/test/CodeGen/Mips/cconv/return-float.ll @@ -30,7 +30,7 @@ entry: ; O32-DAG: lw $2, %lo(float)([[R1]]) ; N32-DAG: lui [[R1:\$[0-9]+]], %hi(float) ; N32-DAG: lw $2, %lo(float)([[R1]]) -; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(float)($1) +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(float)( ; N64-DAG: lw $2, 0([[R1]]) define double @retdouble() nounwind { @@ -44,5 +44,5 @@ entry: ; O32-DAG: addiu [[R2:\$[0-9]+]], [[R1]], %lo(double) ; O32-DAG: lw $3, 4([[R2]]) ; N32-DAG: ld $2, %lo(double)([[R1:\$[0-9]+]]) -; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(double)($1) +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(double)( ; N64-DAG: ld $2, 0([[R1]]) diff --git a/test/CodeGen/Mips/cconv/return-hard-float.ll b/test/CodeGen/Mips/cconv/return-hard-float.ll index 371b3a5..123b499 100644 --- a/test/CodeGen/Mips/cconv/return-hard-float.ll +++ b/test/CodeGen/Mips/cconv/return-hard-float.ll @@ -10,6 +10,9 @@ ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 %s ; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 %s +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static -mattr=+o32,+fp64 < %s | FileCheck --check-prefix=ALL --check-prefix=032FP64 %s +; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static -mattr=+o32,+fp64 < %s | FileCheck --check-prefix=ALL --check-prefix=032FP64 %s + ; Test the float returns for all ABI's and byte orders as specified by ; section 5 of MD00305 (MIPS ABIs Described). @@ -30,7 +33,7 @@ entry: ; O32-DAG: lwc1 $f0, %lo(float)([[R1]]) ; N32-DAG: lui [[R1:\$[0-9]+]], %hi(float) ; N32-DAG: lwc1 $f0, %lo(float)([[R1]]) -; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(float)($1) +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(float)( ; N64-DAG: lwc1 $f0, 0([[R1]]) define double @retdouble() nounwind { @@ -42,5 +45,15 @@ entry: ; ALL-LABEL: retdouble: ; O32-DAG: ldc1 $f0, %lo(double)([[R1:\$[0-9]+]]) ; N32-DAG: ldc1 $f0, %lo(double)([[R1:\$[0-9]+]]) -; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(double)($1) +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(double)( ; N64-DAG: ldc1 $f0, 0([[R1]]) + +define { double, double } @retComplexDouble() #0 { + %retval = alloca { double, double }, align 8 + %1 = load { double, double }* %retval + ret { double, double } %1 +} + +; ALL-LABEL: retComplexDouble: +; 032FP64-DAG: ldc1 $f0, 0($sp) +; 032FP64-DAG: ldc1 $f2, 8($sp) diff --git a/test/CodeGen/Mips/cconv/return-hard-struct-f128.ll b/test/CodeGen/Mips/cconv/return-hard-struct-f128.ll new file mode 100644 index 0000000..2e84477 --- /dev/null +++ b/test/CodeGen/Mips/cconv/return-hard-struct-f128.ll @@ -0,0 +1,36 @@ +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=N32 %s +; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=N32 %s + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 %s +; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 %s + +; Test return of {fp128} agrees with de-facto N32/N64 ABI. + +@struct_fp128 = global {fp128} zeroinitializer + +define inreg {fp128} @ret_struct_fp128() nounwind { +entry: + %0 = load volatile {fp128}* @struct_fp128 + ret {fp128} %0 +} + +; ALL-LABEL: ret_struct_fp128: + +; O32 generates different IR so we don't test it here. It returns the struct +; indirectly. + +; Contrary to the N32/N64 ABI documentation, a struct containing a long double +; is returned in $f0, and $f1 instead of the usual $f0, and $f2. This is to +; match the de facto ABI as implemented by GCC. +; N32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_fp128) +; N32-DAG: ld [[R2:\$[0-9]+]], %lo(struct_fp128)([[R1]]) +; N32-DAG: dmtc1 [[R2]], $f0 +; N32-DAG: addiu [[R3:\$[0-9]+]], [[R1]], %lo(struct_fp128) +; N32-DAG: ld [[R4:\$[0-9]+]], 8([[R3]]) +; N32-DAG: dmtc1 [[R4]], $f1 + +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_fp128)($1) +; N64-DAG: ld [[R2:\$[0-9]+]], 0([[R1]]) +; N64-DAG: dmtc1 [[R2]], $f0 +; N64-DAG: ld [[R4:\$[0-9]+]], 8([[R1]]) +; N64-DAG: dmtc1 [[R4]], $f1 diff --git a/test/CodeGen/Mips/cconv/return-struct.ll b/test/CodeGen/Mips/cconv/return-struct.ll new file mode 100644 index 0000000..11a8cf0 --- /dev/null +++ b/test/CodeGen/Mips/cconv/return-struct.ll @@ -0,0 +1,232 @@ +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-BE %s +; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-LE %s + +; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s +; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=N32 --check-prefix=N32-BE %s +; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=N32 --check-prefix=N32-LE %s + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 --check-prefix=N64-BE %s +; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 --check-prefix=N64-LE %s + +; Test struct returns for all ABI's and byte orders. + +@struct_byte = global {i8} zeroinitializer +@struct_2byte = global {i8,i8} zeroinitializer +@struct_3xi16 = global {[3 x i16]} zeroinitializer +@struct_6xi32 = global {[6 x i32]} zeroinitializer +@struct_128xi16 = global {[128 x i16]} zeroinitializer + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) + +define inreg {i8} @ret_struct_i8() nounwind { +entry: + %0 = load volatile {i8}* @struct_byte + ret {i8} %0 +} + +; ALL-LABEL: ret_struct_i8: +; O32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte) +; O32-DAG: lbu $2, %lo(struct_byte)([[R1]]) + +; N32-LE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte) +; N32-LE-DAG: lb $2, %lo(struct_byte)([[R1]]) + +; N32-BE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte) +; N32-BE-DAG: lb [[R2:\$[0-9]+]], %lo(struct_byte)([[R1]]) +; N32-BE-DAG: dsll $2, [[R2]], 56 + +; N64-LE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_byte)($1) +; N64-LE-DAG: lb $2, 0([[R1]]) + +; N64-BE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_byte)($1) +; N64-BE-DAG: lb [[R2:\$[0-9]+]], 0([[R1]]) +; N64-BE-DAG: dsll $2, [[R2]], 56 + +; This test is based on the way clang currently lowers {i8,i8} to {i16}. +; FIXME: It should probably work for without any lowering too but this doesn't +; work as expected. Each member gets mapped to a register rather than +; packed into a single register. +define inreg {i16} @ret_struct_i16() nounwind { +entry: + %retval = alloca {i8,i8}, align 1 + %0 = bitcast {i8,i8}* %retval to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* getelementptr inbounds ({i8,i8}* @struct_2byte, i32 0, i32 0), i64 2, i32 1, i1 false) + %1 = bitcast {i8,i8}* %retval to {i16}* + %2 = load volatile {i16}* %1 + ret {i16} %2 +} + +; ALL-LABEL: ret_struct_i16: +; O32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte) +; O32-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) +; O32-DAG: sh [[R2]], 0([[SP:\$sp]]) +; O32-DAG: lhu $2, 0([[SP:\$sp]]) + +; N32-LE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte) +; N32-LE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) +; N32-LE-DAG: sh [[R2]], 8([[SP:\$sp]]) +; N32-LE-DAG: lh $2, 8([[SP:\$sp]]) + +; N32-BE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte) +; N32-BE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) +; N32-BE-DAG: sh [[R2]], 8([[SP:\$sp]]) +; N32-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]]) +; N32-BE-DAG: dsll $2, [[R3]], 48 + +; N64-LE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_2byte)($1) +; N64-LE-DAG: lhu [[R2:\$[0-9]+]], 0([[R1]]) +; N64-LE-DAG: sh [[R2]], 8([[SP:\$sp]]) +; N64-LE-DAG: lh $2, 8([[SP:\$sp]]) + +; N64-BE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_2byte)($1) +; N64-BE-DAG: lhu [[R2:\$[0-9]+]], 0([[R1]]) +; N64-BE-DAG: sh [[R2]], 8([[SP:\$sp]]) +; N64-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]]) +; N64-BE-DAG: dsll $2, [[R3]], 48 + +; Ensure that structures bigger than 32-bits but smaller than 64-bits are +; also returned in the upper bits on big endian targets. Previously, these were +; missed by the CCPromoteToType and the shift didn't happen. +define inreg {i48} @ret_struct_3xi16() nounwind { +entry: + %0 = load volatile i48* bitcast ({[3 x i16]}* @struct_3xi16 to i48*), align 2 + %1 = insertvalue {i48} undef, i48 %0, 0 + ret {i48} %1 +} + +; ALL-LABEL: ret_struct_3xi16: + +; O32-BE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; O32-BE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; O32-BE-DAG: lhu [[R1:\$[0-9]+]], 4([[PTR_LO]]) +; O32-BE-DAG: lw [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) +; O32-BE-DAG: sll [[R3:\$[0-9]+]], [[R2]], 16 +; O32-BE-DAG: or $3, [[R1]], [[R3]] +; O32-BE-DAG: srl $2, [[R2]], 16 + +; O32-LE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; O32-LE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; O32-LE-DAG: lhu $3, 4([[PTR_LO]]) +; O32-LE-DAG: lw $2, %lo(struct_3xi16)([[PTR_HI]]) + +; N32-LE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; N32-LE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; N32-LE-DAG: lh [[R1:\$[0-9]+]], 4([[PTR_LO]]) +; N32-LE-DAG: lwu [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) +; N32-LE-DAG: dsll [[R3:\$[0-9]+]], [[R1]], 32 +; N32-LE-DAG: or $2, [[R2]], [[R3]] + +; N32-BE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; N32-BE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; N32-BE-DAG: lw [[R1:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) +; N32-BE-DAG: dsll [[R2:\$[0-9]+]], [[R1]], 16 +; N32-BE-DAG: lhu [[R3:\$[0-9]+]], 4([[PTR_LO]]) +; N32-BE-DAG: or [[R4:\$[0-9]+]], [[R3]], [[R2]] +; N32-BE-DAG: dsll $2, [[R4]], 16 + +; N64-LE-DAG: ld [[PTR:\$[0-9]+]], %got_disp(struct_3xi16)($1) +; N64-LE-DAG: lh [[R1:\$[0-9]+]], 4([[PTR]]) +; N64-LE-DAG: lwu [[R2:\$[0-9]+]], 0([[PTR]]) +; N64-LE-DAG: dsll [[R3:\$[0-9]+]], [[R1]], 32 +; N64-LE-DAG: or $2, [[R2]], [[R3]] + +; N64-BE-DAG: ld [[PTR:\$[0-9]+]], %got_disp(struct_3xi16)($1) +; N64-BE-DAG: lw [[R1:\$[0-9]+]], 0([[PTR]]) +; N64-BE-DAG: dsll [[R2:\$[0-9]+]], [[R1]], 16 +; N64-BE-DAG: lhu [[R3:\$[0-9]+]], 4([[PTR]]) +; N64-BE-DAG: or [[R4:\$[0-9]+]], [[R3]], [[R2]] +; N32-BE-DAG: dsll $2, [[R4]], 16 + +; Ensure that large structures (>128-bit) are returned indirectly. +; We pick an extremely large structure so we don't have to match inlined memcpy's. +define void @ret_struct_128xi16({[128 x i16]}* sret %returnval) { +entry: + %0 = bitcast {[128 x i16]}* %returnval to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* bitcast ({[128 x i16]}* @struct_128xi16 to i8*), i64 256, i32 2, i1 false) + ret void +} + +; ALL-LABEL: ret_struct_128xi16: + +; sret pointer is already in $4 +; O32-DAG: lui [[PTR:\$[0-9]+]], %hi(struct_128xi16) +; O32-DAG: addiu $5, [[PTR]], %lo(struct_128xi16) +; O32: jal memcpy + +; sret pointer is already in $4 +; N32-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_128xi16) +; N32-DAG: addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_128xi16) +; FIXME: This signext isn't necessary. Like integers, pointers are +; but unlike integers, pointers cannot have the signext attribute. +; N32-DAG: sll $5, [[PTR]], 0 +; N32: jal memcpy + +; sret pointer is already in $4 +; N64-DAG: ld $5, %got_disp(struct_128xi16)( +; N64-DAG: ld $25, %call16(memcpy)( +; N64: jalr $25 + +; Ensure that large structures (>128-bit) are returned indirectly. +; This will generate inlined memcpy's anyway so pick the smallest large +; structure +; This time we let the backend lower the sret argument. +define {[6 x i32]} @ret_struct_6xi32() { +entry: + %0 = load volatile {[6 x i32]}* @struct_6xi32, align 2 + ret {[6 x i32]} %0 +} + +; ALL-LABEL: ret_struct_6xi32: + +; sret pointer is already in $4 +; O32-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_6xi32) +; O32-DAG: addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32) +; O32-DAG: lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR]]) +; O32-DAG: lw [[T1:\$[0-9]+]], 4([[PTR]]) +; O32-DAG: lw [[T2:\$[0-9]+]], 8([[PTR]]) +; O32-DAG: lw [[T3:\$[0-9]+]], 12([[PTR]]) +; O32-DAG: lw [[T4:\$[0-9]+]], 16([[PTR]]) +; O32-DAG: lw [[T5:\$[0-9]+]], 20([[PTR]]) +; O32-DAG: sw [[T0]], 0($4) +; O32-DAG: sw [[T1]], 4($4) +; O32-DAG: sw [[T2]], 8($4) +; O32-DAG: sw [[T3]], 12($4) +; O32-DAG: sw [[T4]], 16($4) +; O32-DAG: sw [[T5]], 20($4) + +; FIXME: This signext isn't necessary. Like integers, pointers are +; but unlike integers, pointers cannot have the signext attribute. +; In this case we don't have anywhere to put the signext either since +; the sret argument is invented by the backend. +; N32-DAG: sll [[RET_PTR:\$[0-9]+]], $4, 0 +; N32-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_6xi32) +; N32-DAG: addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32) +; N32-DAG: lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR]]) +; N32-DAG: lw [[T1:\$[0-9]+]], 4([[PTR]]) +; N32-DAG: lw [[T2:\$[0-9]+]], 8([[PTR]]) +; N32-DAG: lw [[T3:\$[0-9]+]], 12([[PTR]]) +; N32-DAG: lw [[T4:\$[0-9]+]], 16([[PTR]]) +; N32-DAG: lw [[T5:\$[0-9]+]], 20([[PTR]]) +; N32-DAG: sw [[T0]], 0([[RET_PTR]]) +; N32-DAG: sw [[T1]], 4([[RET_PTR]]) +; N32-DAG: sw [[T2]], 8([[RET_PTR]]) +; N32-DAG: sw [[T3]], 12([[RET_PTR]]) +; N32-DAG: sw [[T4]], 16([[RET_PTR]]) +; N32-DAG: sw [[T5]], 20([[RET_PTR]]) + +; sret pointer is already in $4 +; N64-DAG: ld [[PTR:\$[0-9]+]], %got_disp(struct_6xi32)( +; N64-DAG: lw [[T0:\$[0-9]+]], 0([[PTR]]) +; N64-DAG: lw [[T1:\$[0-9]+]], 4([[PTR]]) +; N64-DAG: lw [[T2:\$[0-9]+]], 8([[PTR]]) +; N64-DAG: lw [[T3:\$[0-9]+]], 12([[PTR]]) +; N64-DAG: lw [[T4:\$[0-9]+]], 16([[PTR]]) +; N64-DAG: lw [[T5:\$[0-9]+]], 20([[PTR]]) +; N64-DAG: sw [[T0]], 0($4) +; N64-DAG: sw [[T1]], 4($4) +; N64-DAG: sw [[T2]], 8($4) +; N64-DAG: sw [[T3]], 12($4) +; N64-DAG: sw [[T4]], 16($4) +; N64-DAG: sw [[T5]], 20($4) diff --git a/test/CodeGen/Mips/cconv/return.ll b/test/CodeGen/Mips/cconv/return.ll index 76ce5e4..63f9b5f 100644 --- a/test/CodeGen/Mips/cconv/return.ll +++ b/test/CodeGen/Mips/cconv/return.ll @@ -33,7 +33,7 @@ entry: ; O32-DAG: lbu $2, %lo(byte)([[R1]]) ; N32-DAG: lui [[R1:\$[0-9]+]], %hi(byte) ; N32-DAG: lbu $2, %lo(byte)([[R1]]) -; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(byte)($1) +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(byte)( ; N64-DAG: lbu $2, 0([[R1]]) define i32 @reti32() nounwind { @@ -47,7 +47,7 @@ entry: ; O32-DAG: lw $2, %lo(word)([[R1]]) ; N32-DAG: lui [[R1:\$[0-9]+]], %hi(word) ; N32-DAG: lw $2, %lo(word)([[R1]]) -; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(word)($1) +; N64-DAG: ld [[R1:\$[0-9]+]], %got_disp(word)( ; N64-DAG: lw $2, 0([[R1]]) define i64 @reti64() nounwind { diff --git a/test/CodeGen/Mips/cfi_offset.ll b/test/CodeGen/Mips/cfi_offset.ll new file mode 100644 index 0000000..e23855b --- /dev/null +++ b/test/CodeGen/Mips/cfi_offset.ll @@ -0,0 +1,41 @@ +; RUN: llc -march=mips -mattr=+o32 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EB +; RUN: llc -march=mipsel -mattr=+o32 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EL +; RUN: llc -march=mips -mattr=+o32,+fpxx < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EB +; RUN: llc -march=mipsel -mattr=+o32,+fpxx < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EL +; RUN: llc -march=mips -mattr=+o32,+fp64 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EB +; RUN: llc -march=mipsel -mattr=+o32,+fp64 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EL + +@var = global double 0.0 + +declare void @foo(...) + +define void @bar() { + +; CHECK-LABEL: bar: + +; CHECK: .cfi_def_cfa_offset 40 +; CHECK: sdc1 $f22, 32($sp) +; CHECK: sdc1 $f20, 24($sp) +; CHECK: sw $ra, 20($sp) +; CHECK: sw $16, 16($sp) + +; CHECK-EB: .cfi_offset 55, -8 +; CHECK-EB: .cfi_offset 54, -4 +; CHECK-EB: .cfi_offset 53, -16 +; CHECK-EB: .cfi_offset 52, -12 + +; CHECK-EL: .cfi_offset 54, -8 +; CHECK-EL: .cfi_offset 55, -4 +; CHECK-EL: .cfi_offset 52, -16 +; CHECK-EL: .cfi_offset 53, -12 + +; CHECK: .cfi_offset 31, -20 +; CHECK: .cfi_offset 16, -24 + + %val1 = load volatile double* @var + %val2 = load volatile double* @var + call void (...)* @foo() nounwind + store volatile double %val1, double* @var + store volatile double %val2, double* @var + ret void +} diff --git a/test/CodeGen/Mips/cmov.ll b/test/CodeGen/Mips/cmov.ll index 999bdb4..b12c2df 100644 --- a/test/CodeGen/Mips/cmov.ll +++ b/test/CodeGen/Mips/cmov.ll @@ -38,7 +38,7 @@ ; 64-CMP-DAG: or $[[T2:[0-9]+]], $[[T0]], $[[T1]] ; 64-CMP-DAG: ld $2, 0($[[T2]]) -define i32* @cmov1(i32 %s) nounwind readonly { +define i32* @cmov1(i32 signext %s) nounwind readonly { entry: %tobool = icmp ne i32 %s, 0 %tmp1 = load i32** @i3, align 4 @@ -78,7 +78,7 @@ entry: ; 64-CMP-DAG: or $[[T2:[0-9]+]], $[[T0]], $[[T1]] ; 64-CMP-DAG: lw $2, 0($[[T2]]) -define i32 @cmov2(i32 %s) nounwind readonly { +define i32 @cmov2(i32 signext %s) nounwind readonly { entry: %tobool = icmp ne i32 %s, 0 %tmp1 = load i32* @c, align 4 @@ -109,13 +109,46 @@ entry: ; 64-CMP-DAG: selnez $[[T1:[0-9]+]], $6, $[[CC]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @cmov3(i32 %a, i32 %b, i32 %c) nounwind readnone { +define i32 @cmov3(i32 signext %a, i32 signext %b, i32 signext %c) nounwind readnone { entry: %cmp = icmp eq i32 %a, 234 %cond = select i1 %cmp, i32 %b, i32 %c ret i32 %cond } +; ALL-LABEL: cmov3_ne: + +; We won't check the result register since we can't know if the move is first +; or last. We do know it will be either one of two registers so we can at least +; check that. + +; FIXME: Use xori instead of addiu+xor. +; 32-CMOV: addiu $[[R0:[0-9]+]], $zero, 234 +; 32-CMOV: xor $[[R1:[0-9]+]], $4, $[[R0]] +; 32-CMOV: movn ${{[26]}}, $5, $[[R1]] + +; 32-CMP-DAG: xori $[[CC:[0-9]+]], $4, 234 +; 32-CMP-DAG: selnez $[[T0:[0-9]+]], $5, $[[CC]] +; 32-CMP-DAG: seleqz $[[T1:[0-9]+]], $6, $[[CC]] +; 32-CMP-DAG: or $2, $[[T0]], $[[T1]] + +; FIXME: Use xori instead of addiu+xor. +; 64-CMOV: addiu $[[R0:[0-9]+]], $zero, 234 +; 64-CMOV: xor $[[R1:[0-9]+]], $4, $[[R0]] +; 64-CMOV: movn ${{[26]}}, $5, $[[R1]] + +; 64-CMP-DAG: xori $[[CC:[0-9]+]], $4, 234 +; 64-CMP-DAG: selnez $[[T0:[0-9]+]], $5, $[[CC]] +; 64-CMP-DAG: seleqz $[[T1:[0-9]+]], $6, $[[CC]] +; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] + +define i32 @cmov3_ne(i32 signext %a, i32 signext %b, i32 signext %c) nounwind readnone { +entry: + %cmp = icmp ne i32 %a, 234 + %cond = select i1 %cmp, i32 %b, i32 %c + ret i32 %cond +} + ; ALL-LABEL: cmov4: ; We won't check the result register since we can't know if the move is first @@ -146,13 +179,54 @@ entry: ; 64-CMP-DAG: selnez $[[T1:[0-9]+]], $6, $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i64 @cmov4(i32 %a, i64 %b, i64 %c) nounwind readnone { +define i64 @cmov4(i32 signext %a, i64 %b, i64 %c) nounwind readnone { entry: %cmp = icmp eq i32 %a, 234 %cond = select i1 %cmp, i64 %b, i64 %c ret i64 %cond } +; ALL-LABEL: cmov4_ne: + +; We won't check the result register since we can't know if the move is first +; or last. We do know it will be one of two registers so we can at least check +; that. + +; FIXME: Use xori instead of addiu+xor. +; 32-CMOV-DAG: addiu $[[R0:[0-9]+]], $zero, 234 +; 32-CMOV-DAG: xor $[[R1:[0-9]+]], $4, $[[R0]] +; 32-CMOV-DAG: lw $[[R2:2]], 16($sp) +; 32-CMOV-DAG: lw $[[R3:3]], 20($sp) +; 32-CMOV-DAG: movn $[[R2]], $6, $[[R1]] +; 32-CMOV-DAG: movn $[[R3]], $7, $[[R1]] + +; 32-CMP-DAG: xori $[[R0:[0-9]+]], $4, 234 +; 32-CMP-DAG: lw $[[R1:[0-9]+]], 16($sp) +; 32-CMP-DAG: lw $[[R2:[0-9]+]], 20($sp) +; 32-CMP-DAG: selnez $[[T0:[0-9]+]], $6, $[[R0]] +; 32-CMP-DAG: selnez $[[T1:[0-9]+]], $7, $[[R0]] +; 32-CMP-DAG: seleqz $[[T2:[0-9]+]], $[[R1]], $[[R0]] +; 32-CMP-DAG: seleqz $[[T3:[0-9]+]], $[[R2]], $[[R0]] +; 32-CMP-DAG: or $2, $[[T0]], $[[T2]] +; 32-CMP-DAG: or $3, $[[T1]], $[[T3]] + +; FIXME: Use xori instead of addiu+xor. +; 64-CMOV: addiu $[[R0:[0-9]+]], $zero, 234 +; 64-CMOV: xor $[[R1:[0-9]+]], $4, $[[R0]] +; 64-CMOV: movn ${{[26]}}, $5, $[[R1]] + +; 64-CMP-DAG: xori $[[R0:[0-9]+]], $4, 234 +; 64-CMP-DAG: selnez $[[T0:[0-9]+]], $5, $[[R0]] +; 64-CMP-DAG: seleqz $[[T1:[0-9]+]], $6, $[[R0]] +; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] + +define i64 @cmov4_ne(i32 signext %a, i64 %b, i64 %c) nounwind readnone { +entry: + %cmp = icmp ne i32 %a, 234 + %cond = select i1 %cmp, i64 %b, i64 %c + ret i64 %cond +} + ; slti and conditional move. ; ; Check that, pattern @@ -189,7 +263,7 @@ entry: ; 64-CMP-DAG: selnez $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @slti0(i32 %a) { +define i32 @slti0(i32 signext %a) { entry: %cmp = icmp sgt i32 %a, 32766 %cond = select i1 %cmp, i32 3, i32 5 @@ -228,7 +302,7 @@ entry: ; 64-CMP-DAG: seleqz $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @slti1(i32 %a) { +define i32 @slti1(i32 signext %a) { entry: %cmp = icmp sgt i32 %a, 32767 %cond = select i1 %cmp, i32 7, i32 5 @@ -263,7 +337,7 @@ entry: ; 64-CMP-DAG: selnez $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @slti2(i32 %a) { +define i32 @slti2(i32 signext %a) { entry: %cmp = icmp sgt i32 %a, -32769 %cond = select i1 %cmp, i32 3, i32 5 @@ -306,7 +380,7 @@ entry: ; 64-CMP-DAG: seleqz $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @slti3(i32 %a) { +define i32 @slti3(i32 signext %a) { entry: %cmp = icmp sgt i32 %a, -32770 %cond = select i1 %cmp, i32 3, i32 5 @@ -493,7 +567,7 @@ entry: ; 64-CMP-DAG: selnez $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @sltiu0(i32 %a) { +define i32 @sltiu0(i32 signext %a) { entry: %cmp = icmp ugt i32 %a, 32766 %cond = select i1 %cmp, i32 3, i32 5 @@ -532,7 +606,7 @@ entry: ; 64-CMP-DAG: seleqz $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @sltiu1(i32 %a) { +define i32 @sltiu1(i32 signext %a) { entry: %cmp = icmp ugt i32 %a, 32767 %cond = select i1 %cmp, i32 7, i32 5 @@ -567,7 +641,7 @@ entry: ; 64-CMP-DAG: selnez $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @sltiu2(i32 %a) { +define i32 @sltiu2(i32 signext %a) { entry: %cmp = icmp ugt i32 %a, -32769 %cond = select i1 %cmp, i32 3, i32 5 @@ -610,7 +684,7 @@ entry: ; 64-CMP-DAG: seleqz $[[T1:[0-9]+]], $[[I5]], $[[R0]] ; 64-CMP-DAG: or $2, $[[T0]], $[[T1]] -define i32 @sltiu3(i32 %a) { +define i32 @sltiu3(i32 signext %a) { entry: %cmp = icmp ugt i32 %a, -32770 %cond = select i1 %cmp, i32 3, i32 5 @@ -623,7 +697,7 @@ entry: ; doesn't generate conditional moves ; for constant operands whose difference is |1| -define i32 @slti4(i32 %a) nounwind readnone { +define i32 @slti4(i32 signext %a) nounwind readnone { %1 = icmp slt i32 %a, 7 %2 = select i1 %1, i32 4, i32 3 ret i32 %2 @@ -649,7 +723,7 @@ define i32 @slti4(i32 %a) nounwind readnone { ; 64-CMP-NOT: seleqz ; 64-CMP-NOT: selnez -define i32 @slti5(i32 %a) nounwind readnone { +define i32 @slti5(i32 signext %a) nounwind readnone { %1 = icmp slt i32 %a, 7 %2 = select i1 %1, i32 -3, i32 -4 ret i32 %2 @@ -675,7 +749,7 @@ define i32 @slti5(i32 %a) nounwind readnone { ; 64-CMP-NOT: seleqz ; 64-CMP-NOT: selnez -define i32 @slti6(i32 %a) nounwind readnone { +define i32 @slti6(i32 signext %a) nounwind readnone { %1 = icmp slt i32 %a, 7 %2 = select i1 %1, i32 3, i32 4 ret i32 %2 @@ -683,24 +757,9 @@ define i32 @slti6(i32 %a) nounwind readnone { ; ALL-LABEL: slti6: -; 32-CMOV-DAG: slti [[R1:\$[0-9]+]], $4, 7 -; 32-CMOV-DAG: xori [[R1]], [[R1]], 1 -; 32-CMOV-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 -; 32-CMOV-NOT: movn - -; 32-CMP-DAG: slti [[R1:\$[0-9]+]], $4, 7 -; 32-CMP-DAG: xori [[R1]], [[R1]], 1 -; 32-CMP-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 -; 32-CMP-NOT: seleqz -; 32-CMP-NOT: selnez - -; 64-CMOV-DAG: slti [[R1:\$[0-9]+]], $4, 7 -; 64-CMOV-DAG: xori [[R1]], [[R1]], 1 -; 64-CMOV-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 -; 64-CMOV-NOT: movn - -; 64-CMP-DAG: slti [[R1:\$[0-9]+]], $4, 7 -; 64-CMP-DAG: xori [[R1]], [[R1]], 1 -; 64-CMP-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 -; 64-CMP-NOT: seleqz -; 64-CMP-NOT: selnez +; ALL-DAG: addiu [[R1:\$[0-9]+]], $zero, 6 +; ALL-DAG: slt [[R1]], [[R1]], $4 +; ALL-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 +; ALL-NOT: movn +; ALL-NOT: seleqz +; ALL-NOT: selnez diff --git a/test/CodeGen/Mips/const-mult.ll b/test/CodeGen/Mips/const-mult.ll index 1862021..60b2a88 100644 --- a/test/CodeGen/Mips/const-mult.ll +++ b/test/CodeGen/Mips/const-mult.ll @@ -5,7 +5,7 @@ ; CHECK: sll $[[R0:[0-9]+]], $4, 2 ; CHECK: addu ${{[0-9]+}}, $[[R0]], $4 -define i32 @mul5_32(i32 %a) { +define i32 @mul5_32(i32 signext %a) { entry: %mul = mul nsw i32 %a, 5 ret i32 %mul @@ -17,7 +17,7 @@ entry: ; CHECK-DAG: sll $[[R2:[0-9]+]], $4, 5 ; CHECK: subu ${{[0-9]+}}, $[[R2]], $[[R1]] -define i32 @mul27_32(i32 %a) { +define i32 @mul27_32(i32 signext %a) { entry: %mul = mul nsw i32 %a, 27 ret i32 %mul @@ -29,7 +29,7 @@ entry: ; CHECK-DAG: sll $[[R2:[0-9]+]], $4, 31 ; CHECK: addu ${{[0-9]+}}, $[[R2]], $[[R1]] -define i32 @muln2147483643_32(i32 %a) { +define i32 @muln2147483643_32(i32 signext %a) { entry: %mul = mul nsw i32 %a, -2147483643 ret i32 %mul @@ -41,7 +41,7 @@ entry: ; CHECK64-DAG: dsll $[[R2:[0-9]+]], $4, 63 ; CHECK64: daddu ${{[0-9]+}}, $[[R2]], $[[R1]] -define i64 @muln9223372036854775805_64(i64 %a) { +define i64 @muln9223372036854775805_64(i64 signext %a) { entry: %mul = mul nsw i64 %a, -9223372036854775805 ret i64 %mul diff --git a/test/CodeGen/Mips/countleading.ll b/test/CodeGen/Mips/countleading.ll index 6e63cff..b7aad04 100644 --- a/test/CodeGen/Mips/countleading.ll +++ b/test/CodeGen/Mips/countleading.ll @@ -11,7 +11,7 @@ ; MIPS32-GT-R1 - MIPS64r1 and above (does not include MIPS64's) ; MIPS64-GT-R1 - MIPS64r1 and above -define i32 @ctlz_i32(i32 %X) nounwind readnone { +define i32 @ctlz_i32(i32 signext %X) nounwind readnone { entry: ; ALL-LABEL: ctlz_i32: @@ -27,7 +27,7 @@ entry: declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone -define i32 @ctlo_i32(i32 %X) nounwind readnone { +define i32 @ctlo_i32(i32 signext %X) nounwind readnone { entry: ; ALL-LABEL: ctlo_i32: diff --git a/test/CodeGen/Mips/ctlz-v.ll b/test/CodeGen/Mips/ctlz-v.ll index 270f404..3d580e5 100644 --- a/test/CodeGen/Mips/ctlz-v.ll +++ b/test/CodeGen/Mips/ctlz-v.ll @@ -6,12 +6,12 @@ declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) define <2 x i32> @ctlzv2i32(<2 x i32> %x) { entry: ; MIPS32: clz $2, $4 -; MIPS32: jr $ra ; MIPS32: clz $3, $5 -; MIPS64: clz $2, $4 -; MIPS64: jr $ra -; MIPS64: clz $3, $5 +; MIPS64-DAG: sll $[[A0:[0-9]+]], $4, 0 +; MIPS64-DAG: clz $2, $[[A0]] +; MIPS64-DAG: sll $[[A1:[0-9]+]], $5, 0 +; MIPS64-DAG: clz $3, $[[A1]] %ret = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 true) ret <2 x i32> %ret diff --git a/test/CodeGen/Mips/cttz-v.ll b/test/CodeGen/Mips/cttz-v.ll index 9470441..85f69f9 100644 --- a/test/CodeGen/Mips/cttz-v.ll +++ b/test/CodeGen/Mips/cttz-v.ll @@ -18,14 +18,16 @@ entry: ; MIPS32-DAG: jr $ra ; MIPS32-DAG: subu $3, $[[R4]], $[[R8]] -; MIPS64-DAG: addiu $[[R0:[0-9]+]], $4, -1 -; MIPS64-DAG: not $[[R1:[0-9]+]], $4 +; MIPS64-DAG: sll $[[A0:[0-9]+]], $4, 0 +; MIPS64-DAG: addiu $[[R0:[0-9]+]], $[[A0]], -1 +; MIPS64-DAG: not $[[R1:[0-9]+]], $[[A0]] ; MIPS64-DAG: and $[[R2:[0-9]+]], $[[R1]], $[[R0]] ; MIPS64-DAG: clz $[[R3:[0-9]+]], $[[R2]] ; MIPS64-DAG: addiu $[[R4:[0-9]+]], $zero, 32 ; MIPS64-DAG: subu $2, $[[R4]], $[[R3]] -; MIPS64-DAG: addiu $[[R5:[0-9]+]], $5, -1 -; MIPS64-DAG: not $[[R6:[0-9]+]], $5 +; MIPS64-DAG: sll $[[A1:[0-9]+]], $5, 0 +; MIPS64-DAG: addiu $[[R5:[0-9]+]], $[[A1]], -1 +; MIPS64-DAG: not $[[R6:[0-9]+]], $[[A1]] ; MIPS64-DAG: and $[[R7:[0-9]+]], $[[R6]], $[[R5]] ; MIPS64-DAG: clz $[[R8:[0-9]+]], $[[R7]] ; MIPS64-DAG: jr $ra diff --git a/test/CodeGen/Mips/divrem.ll b/test/CodeGen/Mips/divrem.ll index 97f8360..a9cfe0f 100644 --- a/test/CodeGen/Mips/divrem.ll +++ b/test/CodeGen/Mips/divrem.ll @@ -27,7 +27,7 @@ @g0 = common global i32 0, align 4 @g1 = common global i32 0, align 4 -define i32 @sdiv1(i32 %a0, i32 %a1) nounwind readnone { +define i32 @sdiv1(i32 signext %a0, i32 signext %a1) nounwind readnone { entry: ; ALL-LABEL: sdiv1: @@ -54,7 +54,7 @@ entry: ret i32 %div } -define i32 @srem1(i32 %a0, i32 %a1) nounwind readnone { +define i32 @srem1(i32 signext %a0, i32 signext %a1) nounwind readnone { entry: ; ALL-LABEL: srem1: @@ -81,7 +81,7 @@ entry: ret i32 %rem } -define i32 @udiv1(i32 %a0, i32 %a1) nounwind readnone { +define i32 @udiv1(i32 zeroext %a0, i32 zeroext %a1) nounwind readnone { entry: ; ALL-LABEL: udiv1: @@ -107,7 +107,7 @@ entry: ret i32 %div } -define i32 @urem1(i32 %a0, i32 %a1) nounwind readnone { +define i32 @urem1(i32 zeroext %a0, i32 zeroext %a1) nounwind readnone { entry: ; ALL-LABEL: urem1: @@ -134,7 +134,7 @@ entry: ret i32 %rem } -define i32 @sdivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind { +define i32 @sdivrem1(i32 signext %a0, i32 signext %a1, i32* nocapture %r) nounwind { entry: ; ALL-LABEL: sdivrem1: @@ -175,7 +175,7 @@ entry: ret i32 %div } -define i32 @udivrem1(i32 %a0, i32 %a1, i32* nocapture %r) nounwind { +define i32 @udivrem1(i32 zeroext %a0, i32 zeroext %a1, i32* nocapture %r) nounwind { entry: ; ALL-LABEL: udivrem1: diff --git a/test/CodeGen/Mips/ehframe-indirect.ll b/test/CodeGen/Mips/ehframe-indirect.ll index e78497a..b4efb40 100644 --- a/test/CodeGen/Mips/ehframe-indirect.ll +++ b/test/CodeGen/Mips/ehframe-indirect.ll @@ -1,5 +1,7 @@ -; RUN: llc -mtriple=mipsel-linux-gnu < %s | FileCheck %s -; RUN: llc -mtriple=mipsel-linux-android < %s | FileCheck %s +; RUN: llc -mtriple=mipsel-linux-gnu < %s | FileCheck -check-prefix=CHECK32 %s +; RUN: llc -mtriple=mipsel-linux-android < %s | FileCheck -check-prefix=CHECK32 %s +; RUN: llc -mtriple=mips64el-linux-gnu < %s | FileCheck -check-prefix=CHECK64 %s +; RUN: llc -mtriple=mips64el-linux-android < %s | FileCheck -check-prefix=CHECK64 %s define i32 @main() { ; CHECK: .cfi_startproc @@ -27,8 +29,11 @@ declare void @foo() ; CHECK: .hidden DW.ref.__gxx_personality_v0 ; CHECK: .weak DW.ref.__gxx_personality_v0 ; CHECK: .section .data.DW.ref.__gxx_personality_v0,"aGw",@progbits,DW.ref.__gxx_personality_v0,comdat -; CHECK: .align 2 +; CHECK32: .align 2 +; CHECK64: .align 3 ; CHECK: .type DW.ref.__gxx_personality_v0,@object -; CHECK: .size DW.ref.__gxx_personality_v0, 4 +; CHECK32: .size DW.ref.__gxx_personality_v0, 4 +; CHECK64: .size DW.ref.__gxx_personality_v0, 8 ; CHECK: DW.ref.__gxx_personality_v0: -; CHECK: .4byte __gxx_personality_v0 +; CHECK32: .4byte __gxx_personality_v0 +; CHECK64: .8byte __gxx_personality_v0 diff --git a/test/CodeGen/Mips/fastcc.ll b/test/CodeGen/Mips/fastcc.ll index 8ee7af8..6b022c5 100644 --- a/test/CodeGen/Mips/fastcc.ll +++ b/test/CodeGen/Mips/fastcc.ll @@ -1,6 +1,8 @@ ; RUN: llc < %s -march=mipsel | FileCheck %s ; RUN: llc < %s -mtriple=mipsel-none-nacl-gnu \ ; RUN: | FileCheck %s -check-prefix=CHECK-NACL +; RUN: llc < %s -march=mipsel -mcpu=mips32 -mattr=+nooddspreg | FileCheck %s -check-prefix=NOODDSPREG +; RUN: llc < %s -march=mipsel -mcpu=mips32r2 -mattr=+fp64,+nooddspreg | FileCheck %s -check-prefix=FP64-NOODDSPREG @gi0 = external global i32 @@ -80,6 +82,9 @@ @g15 = external global i32 @g16 = external global i32 +@fa = common global [11 x float] zeroinitializer, align 4 +@da = common global [11 x double] zeroinitializer, align 8 + define void @caller0() nounwind { entry: ; CHECK: caller0 @@ -264,3 +269,164 @@ entry: ret void } +define void @caller2() { +entry: + +; NOODDSPREG-LABEL: caller2: + +; Check that first 10 arguments are passed in even float registers +; f0, f2, ... , f18. Check that 11th argument is passed on stack. + +; NOODDSPREG-DAG: lw $[[R0:[0-9]+]], %got(fa)(${{[0-9]+|gp}}) +; NOODDSPREG-DAG: lwc1 $f0, 0($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f2, 4($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f4, 8($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f6, 12($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f8, 16($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f10, 20($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f12, 24($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f14, 28($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f16, 32($[[R0]]) +; NOODDSPREG-DAG: lwc1 $f18, 36($[[R0]]) + +; NOODDSPREG-DAG: lwc1 $[[F0:f[0-9]*[02468]]], 40($[[R0]]) +; NOODDSPREG-DAG: swc1 $[[F0]], 0($sp) + + %0 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 0), align 4 + %1 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 1), align 4 + %2 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 2), align 4 + %3 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 3), align 4 + %4 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 4), align 4 + %5 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 5), align 4 + %6 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 6), align 4 + %7 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 7), align 4 + %8 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 8), align 4 + %9 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 9), align 4 + %10 = load float* getelementptr ([11 x float]* @fa, i32 0, i32 10), align 4 + tail call fastcc void @callee2(float %0, float %1, float %2, float %3, + float %4, float %5, float %6, float %7, + float %8, float %9, float %10) + ret void +} + +define fastcc void @callee2(float %a0, float %a1, float %a2, float %a3, + float %a4, float %a5, float %a6, float %a7, + float %a8, float %a9, float %a10) { +entry: + +; NOODDSPREG-LABEL: callee2: + +; NOODDSPREG: addiu $sp, $sp, -[[OFFSET:[0-9]+]] + +; Check that first 10 arguments are received in even float registers +; f0, f2, ... , f18. Check that 11th argument is received on stack. + +; NOODDSPREG-DAG: lw $[[R0:[0-9]+]], %got(fa)(${{[0-9]+|gp}}) +; NOODDSPREG-DAG: swc1 $f0, 0($[[R0]]) +; NOODDSPREG-DAG: swc1 $f2, 4($[[R0]]) +; NOODDSPREG-DAG: swc1 $f4, 8($[[R0]]) +; NOODDSPREG-DAG: swc1 $f6, 12($[[R0]]) +; NOODDSPREG-DAG: swc1 $f8, 16($[[R0]]) +; NOODDSPREG-DAG: swc1 $f10, 20($[[R0]]) +; NOODDSPREG-DAG: swc1 $f12, 24($[[R0]]) +; NOODDSPREG-DAG: swc1 $f14, 28($[[R0]]) +; NOODDSPREG-DAG: swc1 $f16, 32($[[R0]]) +; NOODDSPREG-DAG: swc1 $f18, 36($[[R0]]) + +; NOODDSPREG-DAG: lwc1 $[[F0:f[0-9]*[02468]]], [[OFFSET]]($sp) +; NOODDSPREG-DAG: swc1 $[[F0]], 40($[[R0]]) + + store float %a0, float* getelementptr ([11 x float]* @fa, i32 0, i32 0), align 4 + store float %a1, float* getelementptr ([11 x float]* @fa, i32 0, i32 1), align 4 + store float %a2, float* getelementptr ([11 x float]* @fa, i32 0, i32 2), align 4 + store float %a3, float* getelementptr ([11 x float]* @fa, i32 0, i32 3), align 4 + store float %a4, float* getelementptr ([11 x float]* @fa, i32 0, i32 4), align 4 + store float %a5, float* getelementptr ([11 x float]* @fa, i32 0, i32 5), align 4 + store float %a6, float* getelementptr ([11 x float]* @fa, i32 0, i32 6), align 4 + store float %a7, float* getelementptr ([11 x float]* @fa, i32 0, i32 7), align 4 + store float %a8, float* getelementptr ([11 x float]* @fa, i32 0, i32 8), align 4 + store float %a9, float* getelementptr ([11 x float]* @fa, i32 0, i32 9), align 4 + store float %a10, float* getelementptr ([11 x float]* @fa, i32 0, i32 10), align 4 + ret void +} + +define void @caller3() { +entry: + +; FP64-NOODDSPREG-LABEL: caller3: + +; Check that first 10 arguments are passed in even float registers +; f0, f2, ... , f18. Check that 11th argument is passed on stack. + +; FP64-NOODDSPREG-DAG: lw $[[R0:[0-9]+]], %got(da)(${{[0-9]+|gp}}) +; FP64-NOODDSPREG-DAG: ldc1 $f0, 0($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f2, 8($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f4, 16($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f6, 24($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f8, 32($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f10, 40($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f12, 48($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f14, 56($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f16, 64($[[R0]]) +; FP64-NOODDSPREG-DAG: ldc1 $f18, 72($[[R0]]) + +; FP64-NOODDSPREG-DAG: ldc1 $[[F0:f[0-9]*[02468]]], 80($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $[[F0]], 0($sp) + + %0 = load double* getelementptr ([11 x double]* @da, i32 0, i32 0), align 8 + %1 = load double* getelementptr ([11 x double]* @da, i32 0, i32 1), align 8 + %2 = load double* getelementptr ([11 x double]* @da, i32 0, i32 2), align 8 + %3 = load double* getelementptr ([11 x double]* @da, i32 0, i32 3), align 8 + %4 = load double* getelementptr ([11 x double]* @da, i32 0, i32 4), align 8 + %5 = load double* getelementptr ([11 x double]* @da, i32 0, i32 5), align 8 + %6 = load double* getelementptr ([11 x double]* @da, i32 0, i32 6), align 8 + %7 = load double* getelementptr ([11 x double]* @da, i32 0, i32 7), align 8 + %8 = load double* getelementptr ([11 x double]* @da, i32 0, i32 8), align 8 + %9 = load double* getelementptr ([11 x double]* @da, i32 0, i32 9), align 8 + %10 = load double* getelementptr ([11 x double]* @da, i32 0, i32 10), align 8 + tail call fastcc void @callee3(double %0, double %1, double %2, double %3, + double %4, double %5, double %6, double %7, + double %8, double %9, double %10) + ret void +} + +define fastcc void @callee3(double %a0, double %a1, double %a2, double %a3, + double %a4, double %a5, double %a6, double %a7, + double %a8, double %a9, double %a10) { +entry: + +; FP64-NOODDSPREG-LABEL: callee3: + +; FP64-NOODDSPREG: addiu $sp, $sp, -[[OFFSET:[0-9]+]] + +; Check that first 10 arguments are received in even float registers +; f0, f2, ... , f18. Check that 11th argument is received on stack. + +; FP64-NOODDSPREG-DAG: lw $[[R0:[0-9]+]], %got(da)(${{[0-9]+|gp}}) +; FP64-NOODDSPREG-DAG: sdc1 $f0, 0($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f2, 8($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f4, 16($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f6, 24($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f8, 32($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f10, 40($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f12, 48($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f14, 56($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f16, 64($[[R0]]) +; FP64-NOODDSPREG-DAG: sdc1 $f18, 72($[[R0]]) + +; FP64-NOODDSPREG-DAG: ldc1 $[[F0:f[0-9]*[02468]]], [[OFFSET]]($sp) +; FP64-NOODDSPREG-DAG: sdc1 $[[F0]], 80($[[R0]]) + + store double %a0, double* getelementptr ([11 x double]* @da, i32 0, i32 0), align 8 + store double %a1, double* getelementptr ([11 x double]* @da, i32 0, i32 1), align 8 + store double %a2, double* getelementptr ([11 x double]* @da, i32 0, i32 2), align 8 + store double %a3, double* getelementptr ([11 x double]* @da, i32 0, i32 3), align 8 + store double %a4, double* getelementptr ([11 x double]* @da, i32 0, i32 4), align 8 + store double %a5, double* getelementptr ([11 x double]* @da, i32 0, i32 5), align 8 + store double %a6, double* getelementptr ([11 x double]* @da, i32 0, i32 6), align 8 + store double %a7, double* getelementptr ([11 x double]* @da, i32 0, i32 7), align 8 + store double %a8, double* getelementptr ([11 x double]* @da, i32 0, i32 8), align 8 + store double %a9, double* getelementptr ([11 x double]* @da, i32 0, i32 9), align 8 + store double %a10, double* getelementptr ([11 x double]* @da, i32 0, i32 10), align 8 + ret void +} diff --git a/test/CodeGen/Mips/fp16instrinsmc.ll b/test/CodeGen/Mips/fp16instrinsmc.ll index 7ced36c..84d3814 100644 --- a/test/CodeGen/Mips/fp16instrinsmc.ll +++ b/test/CodeGen/Mips/fp16instrinsmc.ll @@ -385,7 +385,7 @@ entry: ; Function Attrs: nounwind declare double @exp2(double) #0 -attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" } +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" } attributes #2 = { nounwind readnone } attributes #3 = { nounwind } diff --git a/test/CodeGen/Mips/fp64a.ll b/test/CodeGen/Mips/fp64a.ll new file mode 100644 index 0000000..fadce5c --- /dev/null +++ b/test/CodeGen/Mips/fp64a.ll @@ -0,0 +1,161 @@ +; Test that the FP64A ABI performs double precision moves via a spill/reload. +; The requirement is really that odd-numbered double precision registers do not +; use mfc1/mtc1 to move the bottom 32-bits (because the hardware will redirect +; this to the top 32-bits of the even register) but we have to make the decision +; before register allocation so we do this for all double-precision values. + +; We don't test MIPS32r1 since support for 64-bit coprocessors (such as a 64-bit +; FPU) on a 32-bit architecture was added in MIPS32r2. +; FIXME: We currently don't test that attempting to use FP64 on MIPS32r1 is an +; error either. This is because a large number of CodeGen tests are +; incorrectly using this case. We should fix those test cases then add +; this check here. + +; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NO-FP64A-BE +; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FP64A +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NO-FP64A-LE +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FP64A + +; RUN: llc -march=mips64 -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NO-FP64A +; RUN: not llc -march=mips64 -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A +; RUN: llc -march=mips64el -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NO-FP64A +; RUN: not llc -march=mips64el -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A + +; 64-FP64A: LLVM ERROR: -mattr=+nooddspreg requires the O32 ABI. + +declare double @dbl(); + +define double @call1(double %d, ...) { + ret double %d + +; ALL-LABEL: call1: + +; 32R2-NO-FP64A-LE-NOT: addiu $sp, $sp +; 32R2-NO-FP64A-LE: mtc1 $4, $f0 +; 32R2-NO-FP64A-LE: mthc1 $5, $f0 + +; 32R2-NO-FP64A-BE-NOT: addiu $sp, $sp +; 32R2-NO-FP64A-BE: mtc1 $5, $f0 +; 32R2-NO-FP64A-BE: mthc1 $4, $f0 + +; 32R2-FP64A: addiu $sp, $sp, -8 +; 32R2-FP64A: sw $4, 0($sp) +; 32R2-FP64A: sw $5, 4($sp) +; 32R2-FP64A: ldc1 $f0, 0($sp) + +; 64-NO-FP64A: daddiu $sp, $sp, -64 +; 64-NO-FP64A: mov.d $f0, $f12 +} + +define double @call2(i32 %i, double %d) { + ret double %d + +; ALL-LABEL: call2: + +; 32R2-NO-FP64A-LE: mtc1 $6, $f0 +; 32R2-NO-FP64A-LE: mthc1 $7, $f0 + +; 32R2-NO-FP64A-BE: mtc1 $7, $f0 +; 32R2-NO-FP64A-BE: mthc1 $6, $f0 + +; 32R2-FP64A: addiu $sp, $sp, -8 +; 32R2-FP64A: sw $6, 0($sp) +; 32R2-FP64A: sw $7, 4($sp) +; 32R2-FP64A: ldc1 $f0, 0($sp) + +; 64-NO-FP64A-NOT: daddiu $sp, $sp +; 64-NO-FP64A: mov.d $f0, $f13 +} + +define double @call3(float %f1, float %f2, double %d) { + ret double %d + +; ALL-LABEL: call3: + +; 32R2-NO-FP64A-LE: mtc1 $6, $f0 +; 32R2-NO-FP64A-LE: mthc1 $7, $f0 + +; 32R2-NO-FP64A-BE: mtc1 $7, $f0 +; 32R2-NO-FP64A-BE: mthc1 $6, $f0 + +; 32R2-FP64A: addiu $sp, $sp, -8 +; 32R2-FP64A: sw $6, 0($sp) +; 32R2-FP64A: sw $7, 4($sp) +; 32R2-FP64A: ldc1 $f0, 0($sp) + +; 64-NO-FP64A-NOT: daddiu $sp, $sp +; 64-NO-FP64A: mov.d $f0, $f14 +} + +define double @call4(float %f, double %d, ...) { + ret double %d + +; ALL-LABEL: call4: + +; 32R2-NO-FP64A-LE: mtc1 $6, $f0 +; 32R2-NO-FP64A-LE: mthc1 $7, $f0 + +; 32R2-NO-FP64A-BE: mtc1 $7, $f0 +; 32R2-NO-FP64A-BE: mthc1 $6, $f0 + +; 32R2-FP64A: addiu $sp, $sp, -8 +; 32R2-FP64A: sw $6, 0($sp) +; 32R2-FP64A: sw $7, 4($sp) +; 32R2-FP64A: ldc1 $f0, 0($sp) + +; 64-NO-FP64A: daddiu $sp, $sp, -48 +; 64-NO-FP64A: mov.d $f0, $f13 +} + +define double @call5(double %a, double %b, ...) { + %1 = fsub double %a, %b + ret double %1 + +; ALL-LABEL: call5: + +; 32R2-NO-FP64A-LE-DAG: mtc1 $4, $[[T0:f[0-9]+]] +; 32R2-NO-FP64A-LE-DAG: mthc1 $5, $[[T0:f[0-9]+]] +; 32R2-NO-FP64A-LE-DAG: mtc1 $6, $[[T1:f[0-9]+]] +; 32R2-NO-FP64A-LE-DAG: mthc1 $7, $[[T1:f[0-9]+]] +; 32R2-NO-FP64A-LE: sub.d $f0, $[[T0]], $[[T1]] + +; 32R2-NO-FP64A-BE-DAG: mtc1 $5, $[[T0:f[0-9]+]] +; 32R2-NO-FP64A-BE-DAG: mthc1 $4, $[[T0:f[0-9]+]] +; 32R2-NO-FP64A-BE-DAG: mtc1 $7, $[[T1:f[0-9]+]] +; 32R2-NO-FP64A-BE-DAG: mthc1 $6, $[[T1:f[0-9]+]] +; 32R2-NO-FP64A-BE: sub.d $f0, $[[T0]], $[[T1]] + +; 32R2-FP64A: addiu $sp, $sp, -8 +; 32R2-FP64A: sw $6, 0($sp) +; 32R2-FP64A: sw $7, 4($sp) +; 32R2-FP64A: ldc1 $[[T1:f[0-9]+]], 0($sp) +; 32R2-FP64A: sw $4, 0($sp) +; 32R2-FP64A: sw $5, 4($sp) +; 32R2-FP64A: ldc1 $[[T0:f[0-9]+]], 0($sp) +; 32R2-FP64A: sub.d $f0, $[[T0]], $[[T1]] + +; 64-NO-FP64A: sub.d $f0, $f12, $f13 +} + +define double @move_from(double %d) { + %1 = call double @dbl() + %2 = call double @call2(i32 0, double %1) + ret double %2 + +; ALL-LABEL: move_from: + +; 32R2-NO-FP64A-LE-DAG: mfc1 $6, $f0 +; 32R2-NO-FP64A-LE-DAG: mfhc1 $7, $f0 + +; 32R2-NO-FP64A-BE-DAG: mfc1 $7, $f0 +; 32R2-NO-FP64A-BE-DAG: mfhc1 $6, $f0 + +; 32R2-FP64A: addiu $sp, $sp, -32 +; 32R2-FP64A: sdc1 $f0, 16($sp) +; 32R2-FP64A: lw $6, 16($sp) +; FIXME: This store is redundant +; 32R2-FP64A: sdc1 $f0, 16($sp) +; 32R2-FP64A: lw $7, 20($sp) + +; 64-NO-FP64A: mov.d $f13, $f0 +} diff --git a/test/CodeGen/Mips/fpxx.ll b/test/CodeGen/Mips/fpxx.ll new file mode 100644 index 0000000..7e2ed22 --- /dev/null +++ b/test/CodeGen/Mips/fpxx.ll @@ -0,0 +1,221 @@ +; RUN: llc -march=mipsel -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32-NOFPXX +; RUN: llc -march=mipsel -mcpu=mips32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=32-FPXX + +; RUN: llc -march=mipsel -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NOFPXX +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FPXX + +; RUN: llc -march=mips64 -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL -check-prefix=4-NOFPXX +; RUN: not llc -march=mips64 -mcpu=mips4 -mattr=fpxx < %s 2>&1 | FileCheck %s -check-prefix=4-FPXX + +; RUN: llc -march=mips64 -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NOFPXX +; RUN: not llc -march=mips64 -mcpu=mips64 -mattr=fpxx < %s 2>&1 | FileCheck %s -check-prefix=64-FPXX + +; RUN-TODO: llc -march=mips64 -mcpu=mips4 -mattr=-n64,+o32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=4-O32-NOFPXX +; RUN-TODO: llc -march=mips64 -mcpu=mips4 -mattr=-n64,+o32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=4-O32-FPXX + +; RUN-TODO: llc -march=mips64 -mcpu=mips64 -mattr=-n64,+o32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-O32-NOFPXX +; RUN-TODO: llc -march=mips64 -mcpu=mips64 -mattr=-n64,+o32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-O32-FPXX + +declare double @dbl(); + +; 4-FPXX: LLVM ERROR: FPXX is not permitted for the N32/N64 ABI's. +; 64-FPXX: LLVM ERROR: FPXX is not permitted for the N32/N64 ABI's. + +define double @test1(double %d, ...) { + ret double %d + +; ALL-LABEL: test1: + +; 32-NOFPXX: mtc1 $4, $f0 +; 32-NOFPXX: mtc1 $5, $f1 + +; 32-FPXX: addiu $sp, $sp, -8 +; 32-FPXX: sw $4, 0($sp) +; 32-FPXX: sw $5, 4($sp) +; 32-FPXX: ldc1 $f0, 0($sp) + +; 32R2-NOFPXX: mtc1 $4, $f0 +; 32R2-NOFPXX: mthc1 $5, $f0 + +; 32R2-FPXX: mtc1 $4, $f0 +; 32R2-FPXX: mthc1 $5, $f0 + +; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used. +; 4-NOFPXX: mov.d $f0, $f12 + +; 64-NOFPXX: mov.d $f0, $f12 +} + +define double @test2(i32 %i, double %d) { + ret double %d + +; ALL-LABEL: test2: + +; 32-NOFPXX: mtc1 $6, $f0 +; 32-NOFPXX: mtc1 $7, $f1 + +; 32-FPXX: addiu $sp, $sp, -8 +; 32-FPXX: sw $6, 0($sp) +; 32-FPXX: sw $7, 4($sp) +; 32-FPXX: ldc1 $f0, 0($sp) + +; 32R2-NOFPXX: mtc1 $6, $f0 +; 32R2-NOFPXX: mthc1 $7, $f0 + +; 32R2-FPXX: mtc1 $6, $f0 +; 32R2-FPXX: mthc1 $7, $f0 + +; 4-NOFPXX: mov.d $f0, $f13 + +; 64-NOFPXX: mov.d $f0, $f13 +} + +define double @test3(float %f1, float %f2, double %d) { + ret double %d + +; ALL-LABEL: test3: + +; 32-NOFPXX: mtc1 $6, $f0 +; 32-NOFPXX: mtc1 $7, $f1 + +; 32-FPXX: addiu $sp, $sp, -8 +; 32-FPXX: sw $6, 0($sp) +; 32-FPXX: sw $7, 4($sp) +; 32-FPXX: ldc1 $f0, 0($sp) + +; 32R2-NOFPXX: mtc1 $6, $f0 +; 32R2-NOFPXX: mthc1 $7, $f0 + +; 32R2-FPXX: mtc1 $6, $f0 +; 32R2-FPXX: mthc1 $7, $f0 + +; 4-NOFPXX: mov.d $f0, $f14 + +; 64-NOFPXX: mov.d $f0, $f14 +} + +define double @test4(float %f, double %d, ...) { + ret double %d + +; ALL-LABEL: test4: + +; 32-NOFPXX: mtc1 $6, $f0 +; 32-NOFPXX: mtc1 $7, $f1 + +; 32-FPXX: addiu $sp, $sp, -8 +; 32-FPXX: sw $6, 0($sp) +; 32-FPXX: sw $7, 4($sp) +; 32-FPXX: ldc1 $f0, 0($sp) + +; 32R2-NOFPXX: mtc1 $6, $f0 +; 32R2-NOFPXX: mthc1 $7, $f0 + +; 32R2-FPXX: mtc1 $6, $f0 +; 32R2-FPXX: mthc1 $7, $f0 + +; 4-NOFPXX: mov.d $f0, $f13 + +; 64-NOFPXX: mov.d $f0, $f13 +} + +define double @test5() { + ret double 0.000000e+00 + +; ALL-LABEL: test5: + +; 32-NOFPXX: mtc1 $zero, $f0 +; 32-NOFPXX: mtc1 $zero, $f1 + +; 32-FPXX: addiu $sp, $sp, -8 +; 32-FPXX: sw $zero, 0($sp) +; 32-FPXX: sw $zero, 4($sp) +; 32-FPXX: ldc1 $f0, 0($sp) + +; 32R2-NOFPXX: mtc1 $zero, $f0 +; 32R2-NOFPXX: mthc1 $zero, $f0 + +; 32R2-FPXX: mtc1 $zero, $f0 +; 32R2-FPXX: mthc1 $zero, $f0 + +; 4-NOFPXX: dmtc1 $zero, $f0 + +; 64-NOFPXX: dmtc1 $zero, $f0 +} + +define double @test6(double %a, double %b, ...) { + %1 = fsub double %a, %b + ret double %1 + +; ALL-LABEL: test6: + +; 32-NOFPXX-DAG: mtc1 $4, $[[T0:f[0-9]+]] +; 32-NOFPXX-DAG: mtc1 $5, ${{f[0-9]*[13579]}} +; 32-NOFPXX-DAG: mtc1 $6, $[[T1:f[0-9]+]] +; 32-NOFPXX-DAG: mtc1 $7, ${{f[0-9]*[13579]}} +; 32-NOFPXX: sub.d $f0, $[[T0]], $[[T1]] + +; 32-FPXX: addiu $sp, $sp, -8 +; 32-FPXX: sw $6, 0($sp) +; 32-FPXX: sw $7, 4($sp) +; 32-FPXX: ldc1 $[[T1:f[0-9]+]], 0($sp) +; 32-FPXX: sw $4, 0($sp) +; 32-FPXX: sw $5, 4($sp) +; 32-FPXX: ldc1 $[[T0:f[0-9]+]], 0($sp) +; 32-FPXX: sub.d $f0, $[[T0]], $[[T1]] + +; 32R2-NOFPXX-DAG: mtc1 $4, $[[T0:f[0-9]+]] +; 32R2-NOFPXX-DAG: mthc1 $5, $[[T0]] +; 32R2-NOFPXX-DAG: mtc1 $6, $[[T1:f[0-9]+]] +; 32R2-NOFPXX-DAG: mthc1 $7, $[[T1]] +; 32R2-NOFPXX: sub.d $f0, $[[T0]], $[[T1]] + +; 32R2-FPXX-DAG: mtc1 $4, $[[T0:f[0-9]+]] +; 32R2-FPXX-DAG: mthc1 $5, $[[T0]] +; 32R2-FPXX-DAG: mtc1 $6, $[[T1:f[0-9]+]] +; 32R2-FPXX-DAG: mthc1 $7, $[[T1]] +; 32R2-FPXX: sub.d $f0, $[[T0]], $[[T1]] + +; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used. +; 4-NOFPXX: sub.d $f0, $f12, $f13 + +; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used. +; 64-NOFPXX: sub.d $f0, $f12, $f13 +} + +define double @move_from1(double %d) { + %1 = call double @dbl() + %2 = call double @test2(i32 0, double %1) + ret double %2 + +; ALL-LABEL: move_from1: + +; 32-NOFPXX-DAG: mfc1 $6, $f0 +; 32-NOFPXX-DAG: mfc1 $7, $f1 + +; 32-FPXX: addiu $sp, $sp, -32 +; 32-FPXX: sdc1 $f0, 16($sp) +; 32-FPXX: lw $6, 16($sp) +; FIXME: This store is redundant +; 32-FPXX: sdc1 $f0, 16($sp) +; 32-FPXX: lw $7, 20($sp) + +; 32R2-NOFPXX-DAG: mfc1 $6, $f0 +; 32R2-NOFPXX-DAG: mfhc1 $7, $f0 + +; 32R2-FPXX-DAG: mfc1 $6, $f0 +; 32R2-FPXX-DAG: mfhc1 $7, $f0 + +; floats/doubles are not passed in integer registers for n64, so dmfc1 is not used. +; We can't use inline assembly to force a copy either because trying to force +; a copy to a GPR this way fails with ; "couldn't allocate input reg for +; constraint 'r'". It therefore seems impossible to test the generation of dmfc1 +; in a simple test. +; 4-NOFPXX: mov.d $f13, $f0 + +; floats/doubles are not passed in integer registers for n64, so dmfc1 is not used. +; We can't use inline assembly to force a copy either because trying to force +; a copy to a GPR this way fails with ; "couldn't allocate input reg for +; constraint 'r'". It therefore seems impossible to test the generation of dmfc1 +; in a simple test. +; 64-NOFPXX: mov.d $f13, $f0 +} diff --git a/test/CodeGen/Mips/gpreg-lazy-binding.ll b/test/CodeGen/Mips/gpreg-lazy-binding.ll index 88e596b..3a636d8 100644 --- a/test/CodeGen/Mips/gpreg-lazy-binding.ll +++ b/test/CodeGen/Mips/gpreg-lazy-binding.ll @@ -25,3 +25,11 @@ entry: ret void } +define void @no_lazy(void (i32)* %pf) { + +; CHECK-LABEL: no_lazy +; CHECK-NOT: gp_disp + + tail call void %pf(i32 1) + ret void +} diff --git a/test/CodeGen/Mips/hfptrcall.ll b/test/CodeGen/Mips/hfptrcall.ll index 9df8d90..683952d 100644 --- a/test/CodeGen/Mips/hfptrcall.ll +++ b/test/CodeGen/Mips/hfptrcall.ll @@ -118,8 +118,8 @@ entry: declare i32 @printf(i8*, ...) #1 -attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="true" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="true" } +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/CodeGen/Mips/init-array.ll b/test/CodeGen/Mips/init-array.ll index f96ce26..1ca182d 100644 --- a/test/CodeGen/Mips/init-array.ll +++ b/test/CodeGen/Mips/init-array.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple mipsel-unknown-linux -use-init-array < %s | FileCheck %s +; RUN: llc -mtriple mipsel-unknown-linux < %s | FileCheck %s target triple = "mipsel-unknown-linux" diff --git a/test/CodeGen/Mips/inlineasm-operand-code.ll b/test/CodeGen/Mips/inlineasm-operand-code.ll index 6512851..3d9dec7 100644 --- a/test/CodeGen/Mips/inlineasm-operand-code.ll +++ b/test/CodeGen/Mips/inlineasm-operand-code.ll @@ -65,6 +65,33 @@ entry: ;CHECK_LITTLE_32: addiu ${{[0-9]+}},${{[0-9]+}},$0 ;CHECK_LITTLE_32: #NO_APP tail call i32 asm sideeffect "addiu $0,$1,${2:z}", "=r,r,I"(i32 7, i32 0) nounwind + +; z with non-zero and the "r"(register) and "J"(integer zero) constraints +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: mtc0 ${{[1-9][0-9]?}}, ${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP + call void asm sideeffect "mtc0 ${0:z}, $$12", "Jr"(i32 7) nounwind + +; z with zero and the "r"(register) and "J"(integer zero) constraints +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: mtc0 $0, ${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP + call void asm sideeffect "mtc0 ${0:z}, $$12", "Jr"(i32 0) nounwind + +; z with non-zero and just the "r"(register) constraint +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: mtc0 ${{[1-9][0-9]?}}, ${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP + call void asm sideeffect "mtc0 ${0:z}, $$12", "r"(i32 7) nounwind + +; z with zero and just the "r"(register) constraint +; FIXME: Check for $0, instead of other registers. +; We should be using $0 directly in this case, not real registers. +; When the materialization of 0 gets fixed, this test will fail. +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: mtc0 ${{[1-9][0-9]?}}, ${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP + call void asm sideeffect "mtc0 ${0:z}, $$12", "r"(i32 0) nounwind ret i32 0 } diff --git a/test/CodeGen/Mips/llvm-ir/mul.ll b/test/CodeGen/Mips/llvm-ir/mul.ll new file mode 100644 index 0000000..1674124 --- /dev/null +++ b/test/CodeGen/Mips/llvm-ir/mul.ll @@ -0,0 +1,181 @@ +; RUN: llc < %s -march=mips -mcpu=mips2 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=M2 +; RUN: llc < %s -march=mips -mcpu=mips32 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=32R1-R2 -check-prefix=32R1 +; RUN: llc < %s -march=mips -mcpu=mips32r2 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=32R1-R2 -check-prefix=32R2 +; RUN: llc < %s -march=mips -mcpu=mips32r6 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=32R6 +; RUN: llc < %s -march=mips64 -mcpu=mips4 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=M4 +; RUN: llc < %s -march=mips64 -mcpu=mips64 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=64R1-R2 +; RUN: llc < %s -march=mips64 -mcpu=mips64r2 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=64R1-R2 +; RUN: llc < %s -march=mips64 -mcpu=mips64r6 | FileCheck %s \ +; RUN: -check-prefix=ALL -check-prefix=64R6 + +define signext i1 @mul_i1(i1 signext %a, i1 signext %b) { +entry: +; ALL-LABEL: mul_i1: + + ; M2: mult $4, $5 + ; M2: mflo $[[T0:[0-9]+]] + ; M2: sll $[[T0]], $[[T0]], 31 + ; M2: sra $2, $[[T0]], 31 + + ; 32R1-R2: mul $[[T0:[0-9]+]], $4, $5 + ; 32R1-R2: sll $[[T0]], $[[T0]], 31 + ; 32R1-R2: sra $2, $[[T0]], 31 + + ; 32R6: mul $[[T0:[0-9]+]], $4, $5 + ; 32R6: sll $[[T0]], $[[T0]], 31 + ; 32R6: sra $2, $[[T0]], 31 + + ; M4: mult $4, $5 + ; M4: mflo $[[T0:[0-9]+]] + ; M4: sll $[[T0]], $[[T0]], 31 + ; M4: sra $2, $[[T0]], 31 + + ; 64R1-R2: mul $[[T0:[0-9]+]], $4, $5 + ; 64R1-R2: sll $[[T0]], $[[T0]], 31 + ; 64R1-R2: sra $2, $[[T0]], 31 + + ; 64R6: mul $[[T0:[0-9]+]], $4, $5 + ; 64R6: sll $[[T0]], $[[T0]], 31 + ; 64R6: sra $2, $[[T0]], 31 + + %r = mul i1 %a, %b + ret i1 %r +} + +define signext i8 @mul_i8(i8 signext %a, i8 signext %b) { +entry: +; ALL-LABEL: mul_i8: + + ; M2: mult $4, $5 + ; M2: mflo $[[T0:[0-9]+]] + ; M2: sll $[[T0]], $[[T0]], 24 + ; M2: sra $2, $[[T0]], 24 + + ; 32R1: mul $[[T0:[0-9]+]], $4, $5 + ; 32R1: sll $[[T0]], $[[T0]], 24 + ; 32R1: sra $2, $[[T0]], 24 + + ; 32R2: mul $[[T0:[0-9]+]], $4, $5 + ; 32R2: seb $2, $[[T0]] + + ; 32R6: mul $[[T0:[0-9]+]], $4, $5 + ; 32R6: seb $2, $[[T0]] + + ; M4: mult $4, $5 + ; M4: mflo $[[T0:[0-9]+]] + ; M4: sll $[[T0]], $[[T0]], 24 + ; M4: sra $2, $[[T0]], 24 + + ; 64R1: mul $[[T0:[0-9]+]], $4, $5 + ; 64R1: sll $[[T0]], $[[T0]], 24 + ; 64R1: sra $2, $[[T0]], 24 + + ; 64R2: mul $[[T0:[0-9]+]], $4, $5 + ; 64R2: seb $2, $[[T0]] + + ; 64R6: mul $[[T0:[0-9]+]], $4, $5 + ; 64R6: seb $2, $[[T0]] + %r = mul i8 %a, %b + ret i8 %r +} + +define signext i16 @mul_i16(i16 signext %a, i16 signext %b) { +entry: +; ALL-LABEL: mul_i16: + + ; M2: mult $4, $5 + ; M2: mflo $[[T0:[0-9]+]] + ; M2: sll $[[T0]], $[[T0]], 16 + ; M2: sra $2, $[[T0]], 16 + + ; 32R1: mul $[[T0:[0-9]+]], $4, $5 + ; 32R1: sll $[[T0]], $[[T0]], 16 + ; 32R1: sra $2, $[[T0]], 16 + + ; 32R2: mul $[[T0:[0-9]+]], $4, $5 + ; 32R2: seh $2, $[[T0]] + + ; 32R6: mul $[[T0:[0-9]+]], $4, $5 + ; 32R6: seh $2, $[[T0]] + + ; M4: mult $4, $5 + ; M4: mflo $[[T0:[0-9]+]] + ; M4: sll $[[T0]], $[[T0]], 16 + ; M4: sra $2, $[[T0]], 16 + + ; 64R1: mul $[[T0:[0-9]+]], $4, $5 + ; 64R1: sll $[[T0]], $[[T0]], 16 + ; 64R1: sra $2, $[[T0]], 16 + + ; 64R2: mul $[[T0:[0-9]+]], $4, $5 + ; 64R2: seh $2, $[[T0]] + + ; 64R6: mul $[[T0:[0-9]+]], $4, $5 + ; 64R6: seh $2, $[[T0]] + %r = mul i16 %a, %b + ret i16 %r +} + +define signext i32 @mul_i32(i32 signext %a, i32 signext %b) { +entry: +; ALL-LABEL: mul_i32: + + ; M2: mult $4, $5 + ; M2: mflo $2 + + ; 32R1-R2: mul $2, $4, $5 + ; 32R6: mul $2, $4, $5 + + ; 64R1-R2: mul $2, $4, $5 + ; 64R6: mul $2, $4, $5 + %r = mul i32 %a, %b + ret i32 %r +} + +define signext i64 @mul_i64(i64 signext %a, i64 signext %b) { +entry: +; ALL-LABEL: mul_i64: + + ; M2: mult $4, $7 + ; M2: mflo $[[T0:[0-9]+]] + ; M2: mult $5, $6 + ; M2: mflo $[[T1:[0-9]+]] + ; M2: multu $5, $7 + ; M2: mflo $3 + ; M2: mfhi $4 + ; M2: addu $[[T2:[0-9]+]], $4, $[[T1]] + ; M2: addu $2, $[[T2]], $[[T0]] + + ; 32R1-R2: multu $5, $7 + ; 32R1-R2: mflo $3 + ; 32R1-R2: mfhi $[[T0:[0-9]+]] + ; 32R1-R2: mul $[[T1:[0-9]+]], $4, $7 + ; 32R1-R2: mul $[[T2:[0-9]+]], $5, $6 + ; 32R1-R2: addu $[[T0]], $[[T0]], $[[T2:[0-9]+]] + ; 32R1-R2: addu $2, $[[T0]], $[[T1]] + + ; 32R6: mul $[[T0:[0-9]+]], $5, $6 + ; 32R6: muhu $[[T1:[0-9]+]], $5, $7 + ; 32R6: addu $[[T0]], $[[T1]], $[[T0]] + ; 32R6: mul $[[T2:[0-9]+]], $4, $7 + ; 32R6: addu $2, $[[T0]], $[[T2]] + ; 32R6: mul $3, $5, $7 + + ; M4: dmult $4, $5 + ; M4: mflo $2 + + ; 64R1-R2: dmult $4, $5 + ; 64R1-R2: mflo $2 + + ; 64R6: dmul $2, $4, $5 + + %r = mul i64 %a, %b + ret i64 %r +} diff --git a/test/CodeGen/Mips/load-store-left-right.ll b/test/CodeGen/Mips/load-store-left-right.ll index a3f5ebf..f6d0e8d 100644 --- a/test/CodeGen/Mips/load-store-left-right.ll +++ b/test/CodeGen/Mips/load-store-left-right.ll @@ -47,7 +47,7 @@ entry: ret i32 %0 } -define void @store_SI(i32 %a) nounwind { +define void @store_SI(i32 signext %a) nounwind { entry: ; ALL-LABEL: store_SI: @@ -201,7 +201,7 @@ entry: ret void } -define void @store_SI_trunc_from_i64(i32 %a) nounwind { +define void @store_SI_trunc_from_i64(i32 signext %a) nounwind { entry: ; ALL-LABEL: store_SI_trunc_from_i64: diff --git a/test/CodeGen/Mips/longbranch.ll b/test/CodeGen/Mips/longbranch.ll index a403744..b9b52be 100644 --- a/test/CodeGen/Mips/longbranch.ll +++ b/test/CodeGen/Mips/longbranch.ll @@ -13,7 +13,7 @@ @x = external global i32 -define void @test1(i32 %s) { +define void @test1(i32 signext %s) { entry: %cmp = icmp eq i32 %s, 0 br i1 %cmp, label %end, label %then diff --git a/test/CodeGen/Mips/madd-msub.ll b/test/CodeGen/Mips/madd-msub.ll index 8222967..b0c3ff6 100644 --- a/test/CodeGen/Mips/madd-msub.ll +++ b/test/CodeGen/Mips/madd-msub.ll @@ -76,26 +76,14 @@ entry: ; 32R6-DAG: muhu $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}} ; 32R6-DAG: addu $2, $[[T3]], $[[T2]] -; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32 -; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 -; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32 -; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 -; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]] -; 64-DAG: [[m]]flo $[[T4:[0-9]+]] -; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32 -; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 -; 64-DAG: daddu $2, $[[T4]], $[[T6]] - -; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32 -; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 -; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32 -; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 -; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]] -; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32 -; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 -; 64R6-DAG: daddu $2, $[[T4]], $[[T6]] - -define i64 @madd2(i32 %a, i32 %b, i32 %c) nounwind readnone { +; 64-DAG: d[[m:m]]ult $5, $4 +; 64-DAG: [[m]]flo $[[T0:[0-9]+]] +; 64-DAG: daddu $2, $[[T0]], $6 + +; 64R6-DAG: dmul $[[T0:[0-9]+]], $5, $4 +; 64R6-DAG: daddu $2, $[[T0]], $6 + +define i64 @madd2(i32 zeroext %a, i32 zeroext %b, i32 zeroext %c) nounwind readnone { entry: %conv = zext i32 %a to i64 %conv2 = zext i32 %b to i64 @@ -214,26 +202,14 @@ entry: ; 32R6-DAG: negu $2, $[[T3]] ; 32R6-DAG: subu $3, $6, $[[T1]] -; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32 -; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 -; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32 -; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 -; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]] -; 64-DAG: [[m]]flo $[[T4:[0-9]+]] -; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32 -; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 -; 64-DAG: dsubu $2, $[[T6]], $[[T4]] - -; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32 -; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32 -; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32 -; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32 -; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]] -; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32 -; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32 -; 64R6-DAG: dsubu $2, $[[T6]], $[[T4]] - -define i64 @msub2(i32 %a, i32 %b, i32 %c) nounwind readnone { +; 64-DAG: d[[m:m]]ult $5, $4 +; 64-DAG: [[m]]flo $[[T0:[0-9]+]] +; 64-DAG: dsubu $2, $6, $[[T0]] + +; 64R6-DAG: dmul $[[T0:[0-9]+]], $5, $4 +; 64R6-DAG: dsubu $2, $6, $[[T0]] + +define i64 @msub2(i32 zeroext %a, i32 zeroext %b, i32 zeroext %c) nounwind readnone { entry: %conv = zext i32 %c to i64 %conv2 = zext i32 %a to i64 diff --git a/test/CodeGen/Mips/micromips-addiu.ll b/test/CodeGen/Mips/micromips-addiu.ll new file mode 100644 index 0000000..c5bee34 --- /dev/null +++ b/test/CodeGen/Mips/micromips-addiu.ll @@ -0,0 +1,32 @@ +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ +; RUN: -relocation-model=pic -O3 < %s | FileCheck %s + +@x = global i32 65504, align 4 +@y = global i32 60929, align 4 +@z = global i32 60929, align 4 +@.str = private unnamed_addr constant [7 x i8] c"%08x \0A\00", align 1 + +define i32 @main() nounwind { +entry: + %0 = load i32* @x, align 4 + %addiu1 = add i32 %0, -7 + %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds + ([7 x i8]* @.str, i32 0, i32 0), i32 %addiu1) + + %1 = load i32* @y, align 4 + %addiu2 = add i32 %1, 55 + %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds + ([7 x i8]* @.str, i32 0, i32 0), i32 %addiu2) + + %2 = load i32* @z, align 4 + %addiu3 = add i32 %2, 24 + %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds + ([7 x i8]* @.str, i32 0, i32 0), i32 %addiu3) + ret i32 0 +} + +declare i32 @printf(i8*, ...) + +; CHECK: addius5 ${{[0-9]+}}, -7 +; CHECK: addiu ${{[0-9]+}}, ${{[0-9]+}}, 55 +; CHECK: addiur2 ${{[2-7]|16|17}}, ${{[2-7]|16|17}}, 24 diff --git a/test/CodeGen/Mips/micromips-andi.ll b/test/CodeGen/Mips/micromips-andi.ll new file mode 100644 index 0000000..b82d2b0 --- /dev/null +++ b/test/CodeGen/Mips/micromips-andi.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ +; RUN: -relocation-model=pic -O3 < %s | FileCheck %s + +@x = global i32 65504, align 4 +@y = global i32 60929, align 4 +@.str = private unnamed_addr constant [7 x i8] c"%08x \0A\00", align 1 + +define i32 @main() nounwind { +entry: + %0 = load i32* @x, align 4 + %and1 = and i32 %0, 4 + %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds + ([7 x i8]* @.str, i32 0, i32 0), i32 %and1) + + %1 = load i32* @y, align 4 + %and2 = and i32 %1, 5 + %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds + ([7 x i8]* @.str, i32 0, i32 0), i32 %and2) + ret i32 0 +} + +declare i32 @printf(i8*, ...) + +; CHECK: andi16 ${{[2-7]|16|17}}, ${{[2-7]|16|17}} +; CHECK: andi ${{[0-9]+}}, ${{[0-9]+}} diff --git a/test/CodeGen/Mips/micromips-delay-slot.ll b/test/CodeGen/Mips/micromips-delay-slot.ll new file mode 100644 index 0000000..4bab97a --- /dev/null +++ b/test/CodeGen/Mips/micromips-delay-slot.ll @@ -0,0 +1,18 @@ +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ +; RUN: -relocation-model=pic -O3 < %s | FileCheck %s + +; Function Attrs: nounwind uwtable +define i32 @foo(i32 %a) #0 { +entry: + %a.addr = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + %0 = load i32* %a.addr, align 4 + %shl = shl i32 %0, 2 + %call = call i32 @bar(i32 %shl) + ret i32 %call +} + +declare i32 @bar(i32) #1 + +; CHECK: nop + diff --git a/test/CodeGen/Mips/micromips-rdhwr-directives.ll b/test/CodeGen/Mips/micromips-rdhwr-directives.ll new file mode 100644 index 0000000..af40a87 --- /dev/null +++ b/test/CodeGen/Mips/micromips-rdhwr-directives.ll @@ -0,0 +1,15 @@ +; RUN: llc -march=mipsel -mcpu=mips32 -relocation-model=static < %s \ +; RUN: -mattr=+micromips | FileCheck %s + +@a = external thread_local global i32 + +define i32 @foo() nounwind readonly { +entry: +; CHECK: .set push +; CHECK: .set mips32r2 +; CHECK: rdhwr +; CHECK: .set pop + + %0 = load i32* @a, align 4 + ret i32 %0 +} diff --git a/test/CodeGen/Mips/micromips-shift.ll b/test/CodeGen/Mips/micromips-shift.ll new file mode 100644 index 0000000..8215010 --- /dev/null +++ b/test/CodeGen/Mips/micromips-shift.ll @@ -0,0 +1,44 @@ +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ +; RUN: -relocation-model=pic -O3 < %s | FileCheck %s + +@a = global i32 10, align 4 +@b = global i32 0, align 4 +@c = global i32 10, align 4 +@d = global i32 0, align 4 + +define i32 @shift_left() nounwind { +entry: + %0 = load i32* @a, align 4 + %shl = shl i32 %0, 4 + store i32 %shl, i32* @b, align 4 + + %1 = load i32* @c, align 4 + %shl1 = shl i32 %1, 10 + store i32 %shl1, i32* @d, align 4 + + ret i32 0 +} + +; CHECK: sll16 ${{[2-7]|16|17}}, ${{[2-7]|16|17}}, {{[0-7]}} +; CHECK: sll ${{[0-9]+}}, ${{[0-9]+}}, {{[0-9]+}} + +@i = global i32 10654, align 4 +@j = global i32 0, align 4 +@m = global i32 10, align 4 +@n = global i32 0, align 4 + +define i32 @shift_right() nounwind { +entry: + %0 = load i32* @i, align 4 + %shr = lshr i32 %0, 4 + store i32 %shr, i32* @j, align 4 + + %1 = load i32* @m, align 4 + %shr1 = lshr i32 %1, 10 + store i32 %shr1, i32* @n, align 4 + + ret i32 0 +} + +; CHECK: srl16 ${{[2-7]|16|17}}, ${{[2-7]|16|17}}, {{[0-7]}} +; CHECK: srl ${{[0-9]+}}, ${{[0-9]+}}, {{[0-9]+}} diff --git a/test/CodeGen/Mips/mips16-hf-attr-2.ll b/test/CodeGen/Mips/mips16-hf-attr-2.ll new file mode 100644 index 0000000..60c6eaa --- /dev/null +++ b/test/CodeGen/Mips/mips16-hf-attr-2.ll @@ -0,0 +1,45 @@ +; Check that stubs generation for mips16 hard-float mode does not depend +; on the function 'use-soft-float' attribute's value. +; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel \ +; RUN: -mcpu=mips16 -relocation-model=pic < %s | FileCheck %s + +define void @bar_sf() #1 { +; CHECK: bar_sf: +entry: + %call1 = call float @foo(float 1.000000e+00) +; CHECK: lw $3, %call16(foo)($2) +; CHECK-NOT: lw $5, %got(__mips16_call_stub_sf_1)($3) + ret void +} + +define void @bar_hf() #0 { +; CHECK: bar_hf: +entry: + %call1 = call float @foo(float 1.000000e+00) +; CHECK: lw $2, %call16(foo)($3) +; CHECK: lw $5, %got(__mips16_call_stub_sf_1)($3) + ret void +} + +declare float @foo(float) #2 + +attributes #0 = { + nounwind + "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" + "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" + "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" + "unsafe-fp-math"="false" "use-soft-float"="false" +} +attributes #1 = { + nounwind + "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" + "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" + "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" + "unsafe-fp-math"="false" "use-soft-float"="true" +} +attributes #2 = { + "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" + "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" + "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" + "unsafe-fp-math"="false" "use-soft-float"="true" +} diff --git a/test/CodeGen/Mips/mips16-hf-attr.ll b/test/CodeGen/Mips/mips16-hf-attr.ll index d9ad629..c6ad442 100644 --- a/test/CodeGen/Mips/mips16-hf-attr.ll +++ b/test/CodeGen/Mips/mips16-hf-attr.ll @@ -3,8 +3,8 @@ ; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel \ ; RUN: -mcpu=mips16 -relocation-model=pic < %s | FileCheck %s -define void @bar_sf() #0 { -; CHECK: bar_sf: +define void @bar_hf() #0 { +; CHECK: bar_hf: entry: %call1 = call float @foo(float 1.000000e+00) ; CHECK: lw $2, %call16(foo)($3) @@ -12,12 +12,12 @@ entry: ret void } -define void @bar_hf() #1 { -; CHECK: bar_hf: +define void @bar_sf() #1 { +; CHECK: bar_sf: entry: %call1 = call float @foo(float 1.000000e+00) -; CHECK: lw $2, %call16(foo)($3) -; CHECK: lw $5, %got(__mips16_call_stub_sf_1)($3) +; CHECK: lw $3, %call16(foo)($2) +; CHECK-NOT: lw $5, %got(__mips16_call_stub_sf_1)($3) ret void } diff --git a/test/CodeGen/Mips/mips64-f128.ll b/test/CodeGen/Mips/mips64-f128.ll index 7f7d515..6987d4a 100644 --- a/test/CodeGen/Mips/mips64-f128.ll +++ b/test/CodeGen/Mips/mips64-f128.ll @@ -114,7 +114,7 @@ entry: ; ALL-LABEL: conv_LD_UInt: ; ALL: ld $25, %call16(__floatunsitf) -define fp128 @conv_LD_UInt(i32 %a) { +define fp128 @conv_LD_UInt(i32 signext %a) { entry: %conv = uitofp i32 %a to fp128 ret fp128 %conv @@ -545,7 +545,7 @@ entry: ; ALL-LABEL: load_LD_float: ; ALL: ld $[[R0:[0-9]+]], %got_disp(gf1) -; ALL: lw $4, 0($[[R0]]) +; ALL: lwu $4, 0($[[R0]]) ; ALL: ld $25, %call16(__extendsftf2) ; ALL: jalr $25 @@ -635,7 +635,7 @@ entry: ; CMP_CC_FMT-DAG: selnez $[[NE2:[0-9]+]], $7, $[[CC]] ; CMP_CC_FMT-DAG: or $4, $[[NE2]], $[[EQ2]] -define fp128 @select_LD(i32 %a, i64, fp128 %b, fp128 %c) { +define fp128 @select_LD(i32 signext %a, i64, fp128 %b, fp128 %c) { entry: %tobool = icmp ne i32 %a, 0 %cond = select i1 %tobool, fp128 %b, fp128 %c diff --git a/test/CodeGen/Mips/mips64-sret.ll b/test/CodeGen/Mips/mips64-sret.ll index 7a52c3d..ed494e9 100644 --- a/test/CodeGen/Mips/mips64-sret.ll +++ b/test/CodeGen/Mips/mips64-sret.ll @@ -11,7 +11,7 @@ entry: ret void } -define void @bar(i32 %v, i32* noalias sret %agg.result) nounwind { +define void @bar(i32 signext %v, i32* noalias sret %agg.result) nounwind { entry: ; CHECK-LABEL: bar: ; CHECK: sw $4, 0($5) diff --git a/test/CodeGen/Mips/mno-ldc1-sdc1.ll b/test/CodeGen/Mips/mno-ldc1-sdc1.ll index 244b03d..db653ea 100644 --- a/test/CodeGen/Mips/mno-ldc1-sdc1.ll +++ b/test/CodeGen/Mips/mno-ldc1-sdc1.ll @@ -123,7 +123,7 @@ entry: ; 32R1-LE-PIC-DAG: sw $[[R1]], 4(${{[0-9]+}}) ; 32R2-LE-PIC-DAG: mfc1 $[[R0:[0-9]+]], $f12 -; 32R2-LE-PIC-DAG: mfc1 $[[R1:[0-9]+]], $f13 +; 32R2-LE-PIC-DAG: mfhc1 $[[R1:[0-9]+]], $f12 ; 32R2-LE-PIC-DAG: sw $[[R0]], 0(${{[0-9]+}}) ; 32R2-LE-PIC-DAG: sw $[[R1]], 4(${{[0-9]+}}) @@ -140,7 +140,7 @@ entry: ; 32R1-LE-STATIC-DAG: sw $[[R1]], 4($[[R3]]) ; 32R2-LE-STATIC-DAG: mfc1 $[[R0:[0-9]+]], $f12 -; 32R2-LE-STATIC-DAG: mfc1 $[[R1:[0-9]+]], $f13 +; 32R2-LE-STATIC-DAG: mfhc1 $[[R1:[0-9]+]], $f12 ; 32R2-LE-STATIC-DAG: lui $[[R2:[0-9]+]], %hi(g0) ; 32R2-LE-STATIC-DAG: sw $[[R0]], %lo(g0)($[[R2]]) ; 32R2-LE-STATIC-DAG: addiu $[[R3:[0-9]+]], $[[R2]], %lo(g0) @@ -159,7 +159,7 @@ entry: ; 32R1-BE-PIC-DAG: sw $[[R0]], 4(${{[0-9]+}}) ; 32R2-BE-PIC-DAG: mfc1 $[[R0:[0-9]+]], $f12 -; 32R2-BE-PIC-DAG: mfc1 $[[R1:[0-9]+]], $f13 +; 32R2-BE-PIC-DAG: mfhc1 $[[R1:[0-9]+]], $f12 ; 32R2-BE-PIC-DAG: sw $[[R1]], 0(${{[0-9]+}}) ; 32R2-BE-PIC-DAG: sw $[[R0]], 4(${{[0-9]+}}) @@ -225,7 +225,7 @@ entry: ; 32R1-DAG: sw $[[R1]], 4(${{[0-9]+}}) ; 32R2-DAG: mfc1 $[[R0:[0-9]+]], $f12 -; 32R2-DAG: mfc1 $[[R1:[0-9]+]], $f13 +; 32R2-DAG: mfhc1 $[[R1:[0-9]+]], $f12 ; 32R2-DAG: sw $[[R0]], 0(${{[0-9]+}}) ; 32R2-DAG: sw $[[R1]], 4(${{[0-9]+}}) diff --git a/test/CodeGen/Mips/msa/arithmetic_float.ll b/test/CodeGen/Mips/msa/arithmetic_float.ll index 86e57ac..9aae284 100644 --- a/test/CodeGen/Mips/msa/arithmetic_float.ll +++ b/test/CodeGen/Mips/msa/arithmetic_float.ll @@ -276,8 +276,8 @@ define void @fexp2_v4f32_2(<4 x float>* %c, <4 x float>* %a) nounwind { ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = tail call <4 x float> @llvm.exp2.v4f32 (<4 x float> %1) %3 = fmul <4 x float> <float 2.0, float 2.0, float 2.0, float 2.0>, %2 - ; CHECK-DAG: lui [[R3:\$[0-9]+]], 16384 - ; CHECK-DAG: fill.w [[R4:\$w[0-9]+]], [[R3]] + ; CHECK-DAG: ldi.w [[R3:\$w[0-9]+]], 1 + ; CHECK-DAG: ffint_u.w [[R4:\$w[0-9]+]], [[R3]] ; CHECK-DAG: fexp2.w [[R5:\$w[0-9]+]], [[R4]], [[R1]] store <4 x float> %3, <4 x float>* %c ; CHECK-DAG: st.w [[R5]], 0($4) @@ -287,16 +287,14 @@ define void @fexp2_v4f32_2(<4 x float>* %c, <4 x float>* %a) nounwind { } define void @fexp2_v2f64_2(<2 x double>* %c, <2 x double>* %a) nounwind { - ; CHECK: .8byte 4611686018427387904 - ; CHECK-NEXT: .8byte 4611686018427387904 ; CHECK: fexp2_v2f64_2: %1 = load <2 x double>* %a ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = tail call <2 x double> @llvm.exp2.v2f64 (<2 x double> %1) %3 = fmul <2 x double> <double 2.0, double 2.0>, %2 - ; CHECK-DAG: addiu [[G_PTR:\$[0-9]+]], {{.*}}, %lo($ - ; CHECK-DAG: ld.d [[R3:\$w[0-9]+]], 0([[G_PTR]]) + ; CHECK-DAG: ldi.d [[R2:\$w[0-9]+]], 1 + ; CHECK-DAG: ffint_u.d [[R3:\$w[0-9]+]], [[R2]] ; CHECK-DAG: fexp2.d [[R4:\$w[0-9]+]], [[R3]], [[R1]] store <2 x double> %3, <2 x double>* %c ; CHECK-DAG: st.d [[R4]], 0($4) diff --git a/test/CodeGen/Mips/msa/frameindex.ll b/test/CodeGen/Mips/msa/frameindex.ll index 07e67bf..ebec465 100644 --- a/test/CodeGen/Mips/msa/frameindex.ll +++ b/test/CodeGen/Mips/msa/frameindex.ll @@ -36,10 +36,10 @@ define void @loadstore_v16i8_just_over_simm10() nounwind { %2 = alloca [497 x i8] ; Push the frame just over 512 bytes %3 = load volatile <16 x i8>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 512 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 512 ; MIPS32-AE: ld.b [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <16 x i8> %3, <16 x i8>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 512 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 512 ; MIPS32-AE: st.b [[R1]], 0([[BASE]]) ret void @@ -53,12 +53,12 @@ define void @loadstore_v16i8_just_under_simm16() nounwind { %2 = alloca [32752 x i8] ; Push the frame right up to 32768 bytes %3 = load volatile <16 x i8>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.b [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <16 x i8> %3, <16 x i8>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.b [[R1]], 0([[BASE]]) ret void @@ -72,12 +72,12 @@ define void @loadstore_v16i8_just_over_simm16() nounwind { %2 = alloca [32753 x i8] ; Push the frame just over 32768 bytes %3 = load volatile <16 x i8>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.b [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <16 x i8> %3, <16 x i8>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.b [[R1]], 0([[BASE]]) ret void @@ -107,10 +107,10 @@ define void @loadstore_v8i16_unaligned() nounwind { %5 = getelementptr [2 x <8 x i16>]* %4, i32 0, i32 0 %6 = load volatile <8 x i16>* %5 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1 ; MIPS32-AE: ld.h [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <8 x i16> %6, <8 x i16>* %5 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1 ; MIPS32-AE: st.h [[R1]], 0([[BASE]]) ret void @@ -139,10 +139,10 @@ define void @loadstore_v8i16_just_over_simm10() nounwind { %2 = alloca [1009 x i8] ; Push the frame just over 1024 bytes %3 = load volatile <8 x i16>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1024 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1024 ; MIPS32-AE: ld.h [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <8 x i16> %3, <8 x i16>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1024 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1024 ; MIPS32-AE: st.h [[R1]], 0([[BASE]]) ret void @@ -156,12 +156,12 @@ define void @loadstore_v8i16_just_under_simm16() nounwind { %2 = alloca [32752 x i8] ; Push the frame right up to 32768 bytes %3 = load volatile <8 x i16>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.h [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <8 x i16> %3, <8 x i16>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.h [[R1]], 0([[BASE]]) ret void @@ -175,12 +175,12 @@ define void @loadstore_v8i16_just_over_simm16() nounwind { %2 = alloca [32753 x i8] ; Push the frame just over 32768 bytes %3 = load volatile <8 x i16>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.h [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <8 x i16> %3, <8 x i16>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.h [[R1]], 0([[BASE]]) ret void @@ -210,10 +210,10 @@ define void @loadstore_v4i32_unaligned() nounwind { %5 = getelementptr [2 x <4 x i32>]* %4, i32 0, i32 0 %6 = load volatile <4 x i32>* %5 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1 ; MIPS32-AE: ld.w [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <4 x i32> %6, <4 x i32>* %5 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1 ; MIPS32-AE: st.w [[R1]], 0([[BASE]]) ret void @@ -242,10 +242,10 @@ define void @loadstore_v4i32_just_over_simm10() nounwind { %2 = alloca [2033 x i8] ; Push the frame just over 2048 bytes %3 = load volatile <4 x i32>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 2048 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 2048 ; MIPS32-AE: ld.w [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <4 x i32> %3, <4 x i32>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 2048 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 2048 ; MIPS32-AE: st.w [[R1]], 0([[BASE]]) ret void @@ -259,12 +259,12 @@ define void @loadstore_v4i32_just_under_simm16() nounwind { %2 = alloca [32752 x i8] ; Push the frame right up to 32768 bytes %3 = load volatile <4 x i32>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.w [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <4 x i32> %3, <4 x i32>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.w [[R1]], 0([[BASE]]) ret void @@ -278,12 +278,12 @@ define void @loadstore_v4i32_just_over_simm16() nounwind { %2 = alloca [32753 x i8] ; Push the frame just over 32768 bytes %3 = load volatile <4 x i32>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.w [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <4 x i32> %3, <4 x i32>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.w [[R1]], 0([[BASE]]) ret void @@ -313,10 +313,10 @@ define void @loadstore_v2i64_unaligned() nounwind { %5 = getelementptr [2 x <2 x i64>]* %4, i32 0, i32 0 %6 = load volatile <2 x i64>* %5 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1 ; MIPS32-AE: ld.d [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <2 x i64> %6, <2 x i64>* %5 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 1 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 1 ; MIPS32-AE: st.d [[R1]], 0([[BASE]]) ret void @@ -345,10 +345,10 @@ define void @loadstore_v2i64_just_over_simm10() nounwind { %2 = alloca [4081 x i8] ; Push the frame just over 4096 bytes %3 = load volatile <2 x i64>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 4096 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 4096 ; MIPS32-AE: ld.d [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <2 x i64> %3, <2 x i64>* %1 - ; MIPS32-AE: addiu [[BASE:\$[0-9]+]], $sp, 4096 + ; MIPS32-AE: addiu [[BASE:\$([0-9]+|gp)]], $sp, 4096 ; MIPS32-AE: st.d [[R1]], 0([[BASE]]) ret void @@ -362,12 +362,12 @@ define void @loadstore_v2i64_just_under_simm16() nounwind { %2 = alloca [32752 x i8] ; Push the frame right up to 32768 bytes %3 = load volatile <2 x i64>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.d [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <2 x i64> %3, <2 x i64>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.d [[R1]], 0([[BASE]]) ret void @@ -381,12 +381,12 @@ define void @loadstore_v2i64_just_over_simm16() nounwind { %2 = alloca [32753 x i8] ; Push the frame just over 32768 bytes %3 = load volatile <2 x i64>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: ld.d [[R1:\$w[0-9]+]], 0([[BASE]]) store volatile <2 x i64> %3, <2 x i64>* %1 - ; MIPS32-AE: ori [[R2:\$[0-9]+]], $zero, 32768 - ; MIPS32-AE: addu [[BASE:\$[0-9]+]], $sp, [[R2]] + ; MIPS32-AE: ori [[R2:\$([0-9]+|gp)]], $zero, 32768 + ; MIPS32-AE: addu [[BASE:\$([0-9]+|gp)]], $sp, [[R2]] ; MIPS32-AE: st.d [[R1]], 0([[BASE]]) ret void diff --git a/test/CodeGen/Mips/no-odd-spreg.ll b/test/CodeGen/Mips/no-odd-spreg.ll index b42ed6a..572e940 100644 --- a/test/CodeGen/Mips/no-odd-spreg.ll +++ b/test/CodeGen/Mips/no-odd-spreg.ll @@ -1,10 +1,14 @@ -; RUN: llc -march=mipsel -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=ODDSPREG +; RUN: llc -march=mipsel -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=ODDSPREG -check-prefix=ODDSPREG-NO-EMIT ; RUN: llc -march=mipsel -mcpu=mips32 -mattr=+nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOODDSPREG -; RUN: llc -march=mipsel -mcpu=mips32r6 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=ODDSPREG +; RUN: llc -march=mipsel -mcpu=mips32r6 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=ODDSPREG -check-prefix=ODDSPREG-NO-EMIT ; RUN: llc -march=mipsel -mcpu=mips32r6 -mattr=fp64,+nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOODDSPREG +; RUN: llc -march=mipsel -mcpu=mips32r6 -mattr=fpxx,-nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=ODDSPREG -check-prefix=ODDSPREG-EMIT -; ODDSPREG: .module oddspreg -; NOODDSPREG: .module nooddspreg +; We don't emit a directive unless we need to. This is to support versions of +; GAS which do not support the directive. +; ODDSPREG-EMIT: .module oddspreg +; ODDSPREG-NO-EMIT-NOT: .module oddspreg +; NOODDSPREG: .module nooddspreg define float @two_floats(float %a) { entry: diff --git a/test/CodeGen/Mips/nomips16.ll b/test/CodeGen/Mips/nomips16.ll index 0affb16..5f7d74e 100644 --- a/test/CodeGen/Mips/nomips16.ll +++ b/test/CodeGen/Mips/nomips16.ll @@ -33,6 +33,6 @@ entry: ; CHECK: .end nofoo -attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" } -attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" } +attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/CodeGen/Mips/o32_cc.ll b/test/CodeGen/Mips/o32_cc.ll index 08e5aab..c28f9ab 100644 --- a/test/CodeGen/Mips/o32_cc.ll +++ b/test/CodeGen/Mips/o32_cc.ll @@ -1,12 +1,13 @@ -; RUN: llc -march=mipsel < %s | FileCheck %s -; RUN: llc -march=mipsel -mattr=+fp64 < %s | FileCheck %s -; RUN: llc -march=mipsel < %s | FileCheck -check-prefix=FP32EL %s -; RUN: llc -march=mipsel -mattr=+fp64 < %s | FileCheck -check-prefix=FP64EL %s +; RUN: llc -march=mipsel < %s | FileCheck -check-prefix=ALL %s +; RUN: llc -march=mipsel -mattr=+fp64 < %s | FileCheck -check-prefix=ALL %s +; RUN: llc -march=mipsel -mcpu=mips32 < %s | FileCheck -check-prefix=ALL -check-prefix=NO-MFHC1 %s +; RUN: llc -march=mipsel -mcpu=mips32r2 < %s | FileCheck -check-prefix=ALL -check-prefix=HAS-MFHC1 %s +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+fp64 < %s | FileCheck -check-prefix=ALL -check-prefix=HAS-MFHC1 %s ; $f12, $f14 -; CHECK-LABEL: testlowercall0: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: ldc1 $f14, %lo +; ALL-LABEL: testlowercall0: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: ldc1 $f14, %lo define void @testlowercall0() nounwind { entry: tail call void @f0(double 5.000000e+00, double 6.000000e+00) nounwind @@ -16,9 +17,9 @@ entry: declare void @f0(double, double) ; $f12, $f14 -; CHECK-LABEL: testlowercall1: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: lwc1 $f14, %lo +; ALL-LABEL: testlowercall1: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: lwc1 $f14, %lo define void @testlowercall1() nounwind { entry: tail call void @f1(float 8.000000e+00, float 9.000000e+00) nounwind @@ -28,9 +29,9 @@ entry: declare void @f1(float, float) ; $f12, $f14 -; CHECK-LABEL: testlowercall2: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: ldc1 $f14, %lo +; ALL-LABEL: testlowercall2: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: ldc1 $f14, %lo define void @testlowercall2() nounwind { entry: tail call void @f2(float 8.000000e+00, double 6.000000e+00) nounwind @@ -40,9 +41,9 @@ entry: declare void @f2(float, double) ; $f12, $f14 -; CHECK-LABEL: testlowercall3: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: lwc1 $f14, %lo +; ALL-LABEL: testlowercall3: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: lwc1 $f14, %lo define void @testlowercall3() nounwind { entry: tail call void @f3(double 5.000000e+00, float 9.000000e+00) nounwind @@ -52,11 +53,11 @@ entry: declare void @f3(double, float) ; $4, $5, $6, $7 -; CHECK-LABEL: testlowercall4: -; CHECK-DAG: addiu $4, $zero, 12 -; CHECK-DAG: addiu $5, $zero, 13 -; CHECK-DAG: addiu $6, $zero, 14 -; CHECK-DAG: addiu $7, $zero, 15 +; ALL-LABEL: testlowercall4: +; ALL-DAG: addiu $4, $zero, 12 +; ALL-DAG: addiu $5, $zero, 13 +; ALL-DAG: addiu $6, $zero, 14 +; ALL-DAG: addiu $7, $zero, 15 define void @testlowercall4() nounwind { entry: tail call void @f4(i32 12, i32 13, i32 14, i32 15) nounwind @@ -66,11 +67,11 @@ entry: declare void @f4(i32, i32, i32, i32) ; $f12, $6, stack -; CHECK-LABEL: testlowercall5: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: addiu $6, $zero, 23 -; CHECK-DAG: sw ${{[a-z0-9]+}}, 16($sp) -; CHECK-DAG: sw ${{[a-z0-9]+}}, 20($sp) +; ALL-LABEL: testlowercall5: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: addiu $6, $zero, 23 +; ALL-DAG: sw ${{[a-z0-9]+}}, 16($sp) +; ALL-DAG: sw ${{[a-z0-9]+}}, 20($sp) define void @testlowercall5() nounwind { entry: tail call void @f5(double 1.500000e+01, i32 23, double 1.700000e+01) nounwind @@ -80,10 +81,10 @@ entry: declare void @f5(double, i32, double) ; $f12, $6, $7 -; CHECK-LABEL: testlowercall6: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: addiu $6, $zero, 33 -; CHECK-DAG: addiu $7, $zero, 24 +; ALL-LABEL: testlowercall6: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: addiu $6, $zero, 33 +; ALL-DAG: addiu $7, $zero, 24 define void @testlowercall6() nounwind { entry: tail call void @f6(double 2.500000e+01, i32 33, i32 24) nounwind @@ -93,10 +94,10 @@ entry: declare void @f6(double, i32, i32) ; $f12, $5, $6 -; CHECK-LABEL: testlowercall7: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: addiu $5, $zero, 43 -; CHECK-DAG: addiu $6, $zero, 34 +; ALL-LABEL: testlowercall7: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: addiu $5, $zero, 43 +; ALL-DAG: addiu $6, $zero, 34 define void @testlowercall7() nounwind { entry: tail call void @f7(float 1.800000e+01, i32 43, i32 34) nounwind @@ -106,12 +107,12 @@ entry: declare void @f7(float, i32, i32) ; $4, $5, $6, stack -; CHECK-LABEL: testlowercall8: -; CHECK-DAG: addiu $4, $zero, 22 -; CHECK-DAG: addiu $5, $zero, 53 -; CHECK-DAG: addiu $6, $zero, 44 -; CHECK-DAG: sw ${{[a-z0-9]+}}, 16($sp) -; CHECK-DAG: sw ${{[a-z0-9]+}}, 20($sp) +; ALL-LABEL: testlowercall8: +; ALL-DAG: addiu $4, $zero, 22 +; ALL-DAG: addiu $5, $zero, 53 +; ALL-DAG: addiu $6, $zero, 44 +; ALL-DAG: sw ${{[a-z0-9]+}}, 16($sp) +; ALL-DAG: sw ${{[a-z0-9]+}}, 20($sp) define void @testlowercall8() nounwind { entry: tail call void @f8(i32 22, i32 53, i32 44, double 4.000000e+00) nounwind @@ -121,11 +122,11 @@ entry: declare void @f8(i32, i32, i32, double) ; $4, $5, $6, $7 -; CHECK-LABEL: testlowercall9: -; CHECK-DAG: addiu $4, $zero, 32 -; CHECK-DAG: addiu $5, $zero, 63 -; CHECK-DAG: addiu $6, $zero, 54 -; CHECK-DAG: lui $7, 16688 +; ALL-LABEL: testlowercall9: +; ALL-DAG: addiu $4, $zero, 32 +; ALL-DAG: addiu $5, $zero, 63 +; ALL-DAG: addiu $6, $zero, 54 +; ALL-DAG: lui $7, 16688 define void @testlowercall9() nounwind { entry: tail call void @f9(i32 32, i32 63, i32 54, float 1.100000e+01) nounwind @@ -135,15 +136,16 @@ entry: declare void @f9(i32, i32, i32, float) ; $4, $5, ($6, $7) -; CHECK-LABEL: testlowercall10: -; CHECK-DAG: addiu $4, $zero, 42 -; CHECK-DAG: addiu $5, $zero, 73 -; FP32EL-LABEL: testlowercall10: -; FP32EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP32EL-DAG: mfc1 $7, $f{{[0-9]+}} -; FP64EL-LABEL: testlowercall10: -; FP64EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP64EL-DAG: mfhc1 $7, $f{{[0-9]+}} +; ALL-LABEL: testlowercall10: + +; ALL-DAG: addiu $4, $zero, 42 +; ALL-DAG: addiu $5, $zero, 73 + +; NO-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; NO-MFHC1-DAG: mfc1 $7, $f{{[0-9]+}} + +; HAS-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; HAS-MFHC1-DAG: mfhc1 $7, $f{{[0-9]+}} define void @testlowercall10() nounwind { entry: tail call void @f10(i32 42, i32 73, double 2.700000e+01) nounwind @@ -153,14 +155,14 @@ entry: declare void @f10(i32, i32, double) ; $4, ($6, $7) -; CHECK-LABEL: testlowercall11: -; CHECK-DAG: addiu $4, $zero, 52 -; FP32EL-LABEL: testlowercall11: -; FP32EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP32EL-DAG: mfc1 $7, $f{{[0-9]+}} -; FP64EL-LABEL: testlowercall11: -; FP64EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP64EL-DAG: mfhc1 $7, $f{{[0-9]+}} +; ALL-LABEL: testlowercall11: +; ALL-DAG: addiu $4, $zero, 52 + +; NO-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; NO-MFHC1-DAG: mfc1 $7, $f{{[0-9]+}} + +; HAS-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; HAS-MFHC1-DAG: mfhc1 $7, $f{{[0-9]+}} define void @testlowercall11() nounwind { entry: tail call void @f11(i32 52, double 1.600000e+01) nounwind @@ -170,11 +172,11 @@ entry: declare void @f11(i32, double) ; $f12, $f14, $6, $7 -; CHECK-LABEL: testlowercall12: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: lwc1 $f14, %lo -; CHECK-DAG: lui $6, 16672 -; CHECK-DAG: lui $7, 16808 +; ALL-LABEL: testlowercall12: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: lwc1 $f14, %lo +; ALL-DAG: lui $6, 16672 +; ALL-DAG: lui $7, 16808 define void @testlowercall12() nounwind { entry: tail call void @f12(float 2.800000e+01, float 1.900000e+01, float 1.000000e+01, float 2.100000e+01) nounwind @@ -184,11 +186,11 @@ entry: declare void @f12(float, float, float, float) ; $f12, $5, $6, $7 -; CHECK-LABEL: testlowercall13: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: addiu $5, $zero, 83 -; CHECK-DAG: lui $6, 16800 -; CHECK-DAG: addiu $7, $zero, 25 +; ALL-LABEL: testlowercall13: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: addiu $5, $zero, 83 +; ALL-DAG: lui $6, 16800 +; ALL-DAG: addiu $7, $zero, 25 define void @testlowercall13() nounwind { entry: tail call void @f13(float 3.800000e+01, i32 83, float 2.000000e+01, i32 25) nounwind @@ -199,10 +201,10 @@ entry: declare void @f13(float, i32, float, i32) ; $f12, $f14, $7 -; CHECK-LABEL: testlowercall14: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: lwc1 $f14, %lo -; CHECK-DAG: lui $7, 16880 +; ALL-LABEL: testlowercall14: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: lwc1 $f14, %lo +; ALL-DAG: lui $7, 16880 define void @testlowercall14() nounwind { entry: tail call void @f14(double 3.500000e+01, float 2.900000e+01, float 3.000000e+01) nounwind @@ -212,15 +214,15 @@ entry: declare void @f14(double, float, float) ; $f12, $f14, ($6, $7) -; CHECK-LABEL: testlowercall15: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: lwc1 $f14, %lo -; FP32EL-LABEL: testlowercall15: -; FP32EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP32EL-DAG: mfc1 $7, $f{{[0-9]+}} -; FP64EL-LABEL: testlowercall15: -; FP64EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP64EL-DAG: mfhc1 $7, $f{{[0-9]+}} +; ALL-LABEL: testlowercall15: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: lwc1 $f14, %lo + +; NO-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; NO-MFHC1-DAG: mfc1 $7, $f{{[0-9]+}} + +; HAS-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; HAS-MFHC1-DAG: mfhc1 $7, $f{{[0-9]+}} define void @testlowercall15() nounwind { entry: tail call void @f15(float 4.800000e+01, float 3.900000e+01, double 3.700000e+01) nounwind @@ -230,11 +232,11 @@ entry: declare void @f15(float, float, double) ; $4, $5, $6, $7 -; CHECK-LABEL: testlowercall16: -; CHECK-DAG: addiu $4, $zero, 62 -; CHECK-DAG: lui $5, 16964 -; CHECK-DAG: addiu $6, $zero, 64 -; CHECK-DAG: lui $7, 16888 +; ALL-LABEL: testlowercall16: +; ALL-DAG: addiu $4, $zero, 62 +; ALL-DAG: lui $5, 16964 +; ALL-DAG: addiu $6, $zero, 64 +; ALL-DAG: lui $7, 16888 define void @testlowercall16() nounwind { entry: tail call void @f16(i32 62, float 4.900000e+01, i32 64, float 3.100000e+01) nounwind @@ -244,11 +246,11 @@ entry: declare void @f16(i32, float, i32, float) ; $4, $5, $6, $7 -; CHECK-LABEL: testlowercall17: -; CHECK-DAG: addiu $4, $zero, 72 -; CHECK-DAG: lui $5, 17004 -; CHECK-DAG: addiu $6, $zero, 74 -; CHECK-DAG: addiu $7, $zero, 35 +; ALL-LABEL: testlowercall17: +; ALL-DAG: addiu $4, $zero, 72 +; ALL-DAG: lui $5, 17004 +; ALL-DAG: addiu $6, $zero, 74 +; ALL-DAG: addiu $7, $zero, 35 define void @testlowercall17() nounwind { entry: tail call void @f17(i32 72, float 5.900000e+01, i32 74, i32 35) nounwind @@ -258,11 +260,11 @@ entry: declare void @f17(i32, float, i32, i32) ; $4, $5, $6, $7 -; CHECK-LABEL: testlowercall18: -; CHECK-DAG: addiu $4, $zero, 82 -; CHECK-DAG: addiu $5, $zero, 93 -; CHECK-DAG: lui $6, 16928 -; CHECK-DAG: addiu $7, $zero, 45 +; ALL-LABEL: testlowercall18: +; ALL-DAG: addiu $4, $zero, 82 +; ALL-DAG: addiu $5, $zero, 93 +; ALL-DAG: lui $6, 16928 +; ALL-DAG: addiu $7, $zero, 45 define void @testlowercall18() nounwind { entry: tail call void @f18(i32 82, i32 93, float 4.000000e+01, i32 45) nounwind @@ -273,16 +275,16 @@ declare void @f18(i32, i32, float, i32) ; $4, ($6, $7), stack -; CHECK-LABEL: testlowercall20: -; CHECK-DAG: addiu $4, $zero, 92 -; CHECK-DAG: sw ${{[a-z0-9]+}}, 16($sp) -; CHECK-DAG: sw ${{[a-z0-9]+}}, 20($sp) -; FP32EL-LABEL: testlowercall20: -; FP32EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP32EL-DAG: mfc1 $7, $f{{[0-9]+}} -; FP64EL-LABEL: testlowercall20: -; FP64EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP64EL-DAG: mfhc1 $7, $f{{[0-9]+}} +; ALL-LABEL: testlowercall20: +; ALL-DAG: addiu $4, $zero, 92 +; ALL-DAG: sw ${{[a-z0-9]+}}, 16($sp) +; ALL-DAG: sw ${{[a-z0-9]+}}, 20($sp) + +; NO-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; NO-MFHC1-DAG: mfc1 $7, $f{{[0-9]+}} + +; HAS-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; HAS-MFHC1-DAG: mfhc1 $7, $f{{[0-9]+}} define void @testlowercall20() nounwind { entry: tail call void @f20(i32 92, double 2.600000e+01, double 4.700000e+01) nounwind @@ -292,9 +294,9 @@ entry: declare void @f20(i32, double, double) ; $f12, $5 -; CHECK-LABEL: testlowercall21: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: addiu $5, $zero, 103 +; ALL-LABEL: testlowercall21: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: addiu $5, $zero, 103 define void @testlowercall21() nounwind { entry: tail call void @f21(float 5.800000e+01, i32 103) nounwind @@ -304,15 +306,15 @@ entry: declare void @f21(float, i32) ; $f12, $5, ($6, $7) -; CHECK-LABEL: testlowercall22: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: addiu $5, $zero, 113 -; FP32EL-LABEL: testlowercall22: -; FP32EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP32EL-DAG: mfc1 $7, $f{{[0-9]+}} -; FP64EL-LABEL: testlowercall22: -; FP64EL-DAG: mfc1 $6, $f{{[0-9]+}} -; FP64EL-DAG: mfhc1 $7, $f{{[0-9]+}} +; ALL-LABEL: testlowercall22: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: addiu $5, $zero, 113 + +; NO-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; NO-MFHC1-DAG: mfc1 $7, $f{{[0-9]+}} + +; HAS-MFHC1-DAG: mfc1 $6, $f{{[0-9]+}} +; HAS-MFHC1-DAG: mfhc1 $7, $f{{[0-9]+}} define void @testlowercall22() nounwind { entry: tail call void @f22(float 6.800000e+01, i32 113, double 5.700000e+01) nounwind @@ -322,9 +324,9 @@ entry: declare void @f22(float, i32, double) ; $f12, f6 -; CHECK-LABEL: testlowercall23: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: addiu $6, $zero, 123 +; ALL-LABEL: testlowercall23: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: addiu $6, $zero, 123 define void @testlowercall23() nounwind { entry: tail call void @f23(double 4.500000e+01, i32 123) nounwind @@ -334,11 +336,11 @@ entry: declare void @f23(double, i32) ; $f12,$6, stack -; CHECK-LABEL: testlowercall24: -; CHECK-DAG: ldc1 $f12, %lo -; CHECK-DAG: addiu $6, $zero, 133 -; CHECK-DAG: sw ${{[a-z0-9]+}}, 16($sp) -; CHECK-DAG: sw ${{[a-z0-9]+}}, 20($sp) +; ALL-LABEL: testlowercall24: +; ALL-DAG: ldc1 $f12, %lo +; ALL-DAG: addiu $6, $zero, 133 +; ALL-DAG: sw ${{[a-z0-9]+}}, 16($sp) +; ALL-DAG: sw ${{[a-z0-9]+}}, 20($sp) define void @testlowercall24() nounwind { entry: tail call void @f24(double 5.500000e+01, i32 133, double 6.700000e+01) nounwind @@ -347,19 +349,19 @@ entry: declare void @f24(double, i32, double) -; CHECK-LABEL: testlowercall25: -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: lwc1 $f14, %lo -; CHECK-DAG: lui $6 -; CHECK-DAG: lui $7 -; CHECK-DAG: lwc1 $f12, %lo -; CHECK-DAG: addiu $5, $zero, 83 -; CHECK-DAG: lui $6 -; CHECK-DAG: addiu $7, $zero, 25 -; CHECK-DAG: addiu $4, $zero, 82 -; CHECK-DAG: addiu $5, $zero, 93 -; CHECK-DAG: lui $6 -; CHECK-DAG: addiu $7, $zero, 45 +; ALL-LABEL: testlowercall25: +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: lwc1 $f14, %lo +; ALL-DAG: lui $6 +; ALL-DAG: lui $7 +; ALL-DAG: lwc1 $f12, %lo +; ALL-DAG: addiu $5, $zero, 83 +; ALL-DAG: lui $6 +; ALL-DAG: addiu $7, $zero, 25 +; ALL-DAG: addiu $4, $zero, 82 +; ALL-DAG: addiu $5, $zero, 93 +; ALL-DAG: lui $6 +; ALL-DAG: addiu $7, $zero, 45 define void @testlowercall25() nounwind { entry: tail call void @f12(float 2.800000e+01, float 1.900000e+01, float 1.000000e+01, float 2.100000e+01) nounwind diff --git a/test/CodeGen/Mips/octeon_popcnt.ll b/test/CodeGen/Mips/octeon_popcnt.ll index 52c37f6..3432b39 100644 --- a/test/CodeGen/Mips/octeon_popcnt.ll +++ b/test/CodeGen/Mips/octeon_popcnt.ll @@ -6,7 +6,7 @@ define i8 @cnt8(i8 %x) nounwind readnone { ret i8 %cnt ; OCTEON-LABEL: cnt8: ; OCTEON: jr $ra -; OCTEON: pop $2, $1 +; OCTEON: pop $2, [[R1:\$[0-9]+]] ; MIPS64-LABEL: cnt8: ; MIPS64-NOT: pop } @@ -16,12 +16,12 @@ define i16 @cnt16(i16 %x) nounwind readnone { ret i16 %cnt ; OCTEON-LABEL: cnt16: ; OCTEON: jr $ra -; OCTEON: pop $2, $1 +; OCTEON: pop $2, [[R1:\$[0-9]+]] ; MIPS64-LABEL: cnt16: ; MIPS64-NOT: pop } -define i32 @cnt32(i32 %x) nounwind readnone { +define i32 @cnt32(i32 zeroext %x) nounwind readnone { %cnt = tail call i32 @llvm.ctpop.i32(i32 %x) ret i32 %cnt ; OCTEON-LABEL: cnt32: diff --git a/test/CodeGen/Mips/prevent-hoisting.ll b/test/CodeGen/Mips/prevent-hoisting.ll index da665c2..210fe3b 100644 --- a/test/CodeGen/Mips/prevent-hoisting.ll +++ b/test/CodeGen/Mips/prevent-hoisting.ll @@ -10,16 +10,19 @@ ; CHECK-LABEL: readLumaCoeff8x8_CABAC -; The check for "addiu" instruction is added so that we can match the correct "b" instruction. +; The check for first "addiu" instruction is added so that we can match the correct "b" instruction. ; CHECK: addiu ${{[0-9]+}}, $zero, -1 ; CHECK: b $[[BB0:BB[0-9_]+]] +; CHECK-NEXT: addiu ${{[0-9]+}}, $zero, 0 -; Check that sll instruction that writes to $1 starts basic block. -; CHECK: {{BB[0-9_#]+}}: +; Check that at the start of a fallthrough block there is a instruction that writes to $1. +; CHECK-NEXT: {{BB[0-9_#]+}}: +; CHECK-NEXT: lw $[[R1:[0-9]+]], %got(assignSE2partition)($[[R2:[0-9]+]]) ; CHECK-NEXT: sll $1, $[[R0:[0-9]+]], 4 -; Check that identical sll instruction starts another basic block. +; Check that identical instructions are at the start of a target block. ; CHECK: [[BB0]]: +; CHECK-NEXT: lw $[[R1]], %got(assignSE2partition)($[[R2]]) ; CHECK-NEXT: sll $1, $[[R0]], 4 diff --git a/test/CodeGen/Mips/select.ll b/test/CodeGen/Mips/select.ll index eb2198b..d6e1826 100644 --- a/test/CodeGen/Mips/select.ll +++ b/test/CodeGen/Mips/select.ll @@ -8,7 +8,7 @@ @d2 = external global double @d3 = external global double -define i32 @i32_icmp_ne_i32_val(i32 %s, i32 %f0, i32 %f1) nounwind readnone { +define i32 @i32_icmp_ne_i32_val(i32 signext %s, i32 signext %f0, i32 signext %f1) nounwind readnone { entry: ; ALL-LABEL: i32_icmp_ne_i32_val: @@ -37,7 +37,7 @@ entry: ret i32 %cond } -define i64 @i32_icmp_ne_i64_val(i32 %s, i64 %f0, i64 %f1) nounwind readnone { +define i64 @i32_icmp_ne_i64_val(i32 signext %s, i64 %f0, i64 %f1) nounwind readnone { entry: ; ALL-LABEL: i32_icmp_ne_i64_val: @@ -128,7 +128,7 @@ entry: ret i64 %cond } -define float @i32_icmp_ne_f32_val(i32 %s, float %f0, float %f1) nounwind readnone { +define float @i32_icmp_ne_f32_val(i32 signext %s, float %f0, float %f1) nounwind readnone { entry: ; ALL-LABEL: i32_icmp_ne_f32_val: @@ -161,7 +161,7 @@ entry: ret float %cond } -define double @i32_icmp_ne_f64_val(i32 %s, double %f0, double %f1) nounwind readnone { +define double @i32_icmp_ne_f64_val(i32 signext %s, double %f0, double %f1) nounwind readnone { entry: ; ALL-LABEL: i32_icmp_ne_f64_val: @@ -496,7 +496,7 @@ entry: ret float %cond } -define i32 @f32_fcmp_oeq_i32_val(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone { +define i32 @f32_fcmp_oeq_i32_val(i32 signext %f0, i32 signext %f1, float %f2, float %f3) nounwind readnone { entry: ; ALL-LABEL: f32_fcmp_oeq_i32_val: @@ -541,7 +541,7 @@ entry: ret i32 %cond } -define i32 @f32_fcmp_olt_i32_val(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone { +define i32 @f32_fcmp_olt_i32_val(i32 signext %f0, i32 signext %f1, float %f2, float %f3) nounwind readnone { entry: ; ALL-LABEL: f32_fcmp_olt_i32_val: @@ -585,7 +585,7 @@ entry: ret i32 %cond } -define i32 @f32_fcmp_ogt_i32_val(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone { +define i32 @f32_fcmp_ogt_i32_val(i32 signext %f0, i32 signext %f1, float %f2, float %f3) nounwind readnone { entry: ; ALL-LABEL: f32_fcmp_ogt_i32_val: @@ -630,7 +630,7 @@ entry: ret i32 %cond } -define i32 @f64_fcmp_oeq_i32_val(i32 %f0, i32 %f1) nounwind readonly { +define i32 @f64_fcmp_oeq_i32_val(i32 signext %f0, i32 signext %f1) nounwind readonly { entry: ; ALL-LABEL: f64_fcmp_oeq_i32_val: @@ -707,7 +707,7 @@ entry: ret i32 %cond } -define i32 @f64_fcmp_olt_i32_val(i32 %f0, i32 %f1) nounwind readonly { +define i32 @f64_fcmp_olt_i32_val(i32 signext %f0, i32 signext %f1) nounwind readonly { entry: ; ALL-LABEL: f64_fcmp_olt_i32_val: @@ -784,7 +784,7 @@ entry: ret i32 %cond } -define i32 @f64_fcmp_ogt_i32_val(i32 %f0, i32 %f1) nounwind readonly { +define i32 @f64_fcmp_ogt_i32_val(i32 signext %f0, i32 signext %f1) nounwind readonly { entry: ; ALL-LABEL: f64_fcmp_ogt_i32_val: diff --git a/test/CodeGen/Mips/seleq.ll b/test/CodeGen/Mips/seleq.ll index 190baad..9af422f 100644 --- a/test/CodeGen/Mips/seleq.ll +++ b/test/CodeGen/Mips/seleq.ll @@ -10,7 +10,7 @@ @z3 = common global i32 0, align 4 @z4 = common global i32 0, align 4 -define void @calc_seleq() nounwind "target-cpu"="mips32" "target-features"="+o32,+mips32" { +define void @calc_seleq() nounwind { entry: %0 = load i32* @a, align 4 %1 = load i32* @b, align 4 diff --git a/test/CodeGen/Mips/small-section-reserve-gp.ll b/test/CodeGen/Mips/small-section-reserve-gp.ll index 03503fb..cbf0681 100644 --- a/test/CodeGen/Mips/small-section-reserve-gp.ll +++ b/test/CodeGen/Mips/small-section-reserve-gp.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=mipsel-sde-elf -march=mipsel -relocation-model=static < %s \ +; RUN: llc -mtriple=mipsel-sde-elf -march=mipsel -relocation-model=static -mattr=+noabicalls -mgpopt < %s \ ; RUN: | FileCheck %s @i = internal unnamed_addr global i32 0, align 4 diff --git a/test/CodeGen/Mips/start-asm-file.ll b/test/CodeGen/Mips/start-asm-file.ll index 8872464..9dc501c 100644 --- a/test/CodeGen/Mips/start-asm-file.ll +++ b/test/CodeGen/Mips/start-asm-file.ll @@ -1,7 +1,4 @@ ; Check the emission of directives at the start of an asm file. -; This test is XFAILED until we fix the emission of '.option pic0' on -; N32. At the moment we check if subtarget is Mips64 when we should be -; checking the Subtarget's ABI. ; ### O32 ABI ### ; RUN: llc -filetype=asm -mtriple mips-unknown-linux -mcpu=mips32 \ diff --git a/test/CodeGen/Mips/zeroreg.ll b/test/CodeGen/Mips/zeroreg.ll index a1b6cb0..c766d3b 100644 --- a/test/CodeGen/Mips/zeroreg.ll +++ b/test/CodeGen/Mips/zeroreg.ll @@ -8,7 +8,7 @@ @g1 = external global i32 -define i32 @sel_icmp_nez_i32_z0(i32 %s) nounwind readonly { +define i32 @sel_icmp_nez_i32_z0(i32 signext %s) nounwind readonly { entry: ; ALL-LABEL: sel_icmp_nez_i32_z0: @@ -30,7 +30,7 @@ entry: ret i32 %cond } -define i32 @sel_icmp_nez_i32_z1(i32 %s) nounwind readonly { +define i32 @sel_icmp_nez_i32_z1(i32 signext %s) nounwind readonly { entry: ; ALL-LABEL: sel_icmp_nez_i32_z1: |