summaryrefslogtreecommitdiffstats
path: root/test/CodeGen/Mips/llvm-ir
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGen/Mips/llvm-ir')
-rw-r--r--test/CodeGen/Mips/llvm-ir/call.ll166
-rw-r--r--test/CodeGen/Mips/llvm-ir/indirectbr.ll34
-rw-r--r--test/CodeGen/Mips/llvm-ir/ret.ll205
3 files changed, 405 insertions, 0 deletions
diff --git a/test/CodeGen/Mips/llvm-ir/call.ll b/test/CodeGen/Mips/llvm-ir/call.ll
new file mode 100644
index 0000000..4cbf43c
--- /dev/null
+++ b/test/CodeGen/Mips/llvm-ir/call.ll
@@ -0,0 +1,166 @@
+; Test the 'call' instruction and the tailcall variant.
+
+; FIXME: We should remove the need for -enable-mips-tail-calls
+; RUN: llc -march=mips -mcpu=mips32 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
+; RUN: llc -march=mips -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
+; RUN: llc -march=mips -mcpu=mips32r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
+; RUN: llc -march=mips64 -mcpu=mips4 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
+; RUN: llc -march=mips64 -mcpu=mips64 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
+; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
+; RUN: llc -march=mips64 -mcpu=mips64r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
+
+declare void @extern_void_void()
+declare i32 @extern_i32_void()
+declare float @extern_float_void()
+
+define i32 @call_void_void() {
+; ALL-LABEL: call_void_void:
+
+; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
+
+; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
+
+; ALL: jalr $[[TGT]]
+
+ call void @extern_void_void()
+ ret i32 0
+}
+
+define i32 @call_i32_void() {
+; ALL-LABEL: call_i32_void:
+
+; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
+
+; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
+
+; ALL: jalr $[[TGT]]
+
+ %1 = call i32 @extern_i32_void()
+ %2 = add i32 %1, 1
+ ret i32 %2
+}
+
+define float @call_float_void() {
+; ALL-LABEL: call_float_void:
+
+; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
+; look into it at some point.
+; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
+; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
+
+; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
+
+; ALL: jalr $[[TGT]]
+
+; O32: move $gp, $[[GP]]
+
+ %1 = call float @extern_float_void()
+ %2 = fadd float %1, 1.0
+ ret float %2
+}
+
+define void @musttail_call_void_void() {
+; ALL-LABEL: musttail_call_void_void:
+
+; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
+
+; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
+
+; NOT-R6: jr $[[TGT]]
+; R6: r6.jr $[[TGT]]
+
+ musttail call void @extern_void_void()
+ ret void
+}
+
+define i32 @musttail_call_i32_void() {
+; ALL-LABEL: musttail_call_i32_void:
+
+; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
+
+; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
+
+; NOT-R6: jr $[[TGT]]
+; R6: r6.jr $[[TGT]]
+
+ %1 = musttail call i32 @extern_i32_void()
+ ret i32 %1
+}
+
+define float @musttail_call_float_void() {
+; ALL-LABEL: musttail_call_float_void:
+
+; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
+
+; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
+
+; NOT-R6: jr $[[TGT]]
+; R6: r6.jr $[[TGT]]
+
+ %1 = musttail call float @extern_float_void()
+ ret float %1
+}
+
+define i32 @indirect_call_void_void(void ()* %addr) {
+; ALL-LABEL: indirect_call_void_void:
+
+; ALL: move $25, $4
+; ALL: jalr $25
+
+ call void %addr()
+ ret i32 0
+}
+
+define i32 @indirect_call_i32_void(i32 ()* %addr) {
+; ALL-LABEL: indirect_call_i32_void:
+
+; ALL: move $25, $4
+; ALL: jalr $25
+
+ %1 = call i32 %addr()
+ %2 = add i32 %1, 1
+ ret i32 %2
+}
+
+define float @indirect_call_float_void(float ()* %addr) {
+; ALL-LABEL: indirect_call_float_void:
+
+; ALL: move $25, $4
+; ALL: jalr $25
+
+ %1 = call float %addr()
+ %2 = fadd float %1, 1.0
+ ret float %2
+}
+
+; We can't use 'musttail' here because the verifier is too conservative and
+; prohibits any prototype difference.
+define void @tail_indirect_call_void_void(void ()* %addr) {
+; ALL-LABEL: tail_indirect_call_void_void:
+
+; ALL: move $25, $4
+; ALL: jr $25
+
+ tail call void %addr()
+ ret void
+}
+
+define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
+; ALL-LABEL: tail_indirect_call_i32_void:
+
+; ALL: move $25, $4
+; ALL: jr $25
+
+ %1 = tail call i32 %addr()
+ ret i32 %1
+}
+
+define float @tail_indirect_call_float_void(float ()* %addr) {
+; ALL-LABEL: tail_indirect_call_float_void:
+
+; ALL: move $25, $4
+; ALL: jr $25
+
+ %1 = tail call float %addr()
+ ret float %1
+}
diff --git a/test/CodeGen/Mips/llvm-ir/indirectbr.ll b/test/CodeGen/Mips/llvm-ir/indirectbr.ll
new file mode 100644
index 0000000..d8fd787
--- /dev/null
+++ b/test/CodeGen/Mips/llvm-ir/indirectbr.ll
@@ -0,0 +1,34 @@
+; Test all important variants of the unconditional 'br' instruction.
+
+; RUN: llc -march=mips -mcpu=mips32 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6
+; RUN: llc -march=mips -mcpu=mips32r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6
+; RUN: llc -march=mips -mcpu=mips32r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=R6
+; RUN: llc -march=mips64 -mcpu=mips4 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6
+; RUN: llc -march=mips64 -mcpu=mips64 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6
+; RUN: llc -march=mips64 -mcpu=mips64r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOT-R6
+; RUN: llc -march=mips64 -mcpu=mips64r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=R6
+
+define i32 @br(i8 *%addr) {
+; ALL-LABEL: br:
+; NOT-R6: jr $4 # <MCInst #{{[0-9]+}} JR
+; R6: jr $4 # <MCInst #{{[0-9]+}} JALR
+
+; ALL: $BB0_1: # %L1
+; NOT-R6: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6: jr $ra # <MCInst #{{[0-9]+}} JALR
+; ALL: addiu $2, $zero, 0
+
+; ALL: $BB0_2: # %L2
+; NOT-R6: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6: jr $ra # <MCInst #{{[0-9]+}} JALR
+; ALL: addiu $2, $zero, 1
+
+entry:
+ indirectbr i8* %addr, [label %L1, label %L2]
+
+L1:
+ ret i32 0
+
+L2:
+ ret i32 1
+}
diff --git a/test/CodeGen/Mips/llvm-ir/ret.ll b/test/CodeGen/Mips/llvm-ir/ret.ll
new file mode 100644
index 0000000..8f5b115
--- /dev/null
+++ b/test/CodeGen/Mips/llvm-ir/ret.ll
@@ -0,0 +1,205 @@
+; Test all important variants of the 'ret' instruction.
+;
+; For non-void returns it is necessary to have something to return so we also
+; test constant generation here.
+;
+; We'll test pointer returns in a separate file since the relocation model
+; affects it and it's undesirable to repeat the non-pointer returns for each
+; relocation model.
+
+; RUN: llc -march=mips -mcpu=mips32 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=NO-MTHC1 -check-prefix=NOT-R6
+; RUN: llc -march=mips -mcpu=mips32r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=NOT-R6
+; RUN: llc -march=mips -mcpu=mips32r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1 -check-prefix=R6
+; RUN: llc -march=mips64 -mcpu=mips4 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6
+; RUN: llc -march=mips64 -mcpu=mips64 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6
+; RUN: llc -march=mips64 -mcpu=mips64r2 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=NOT-R6
+; RUN: llc -march=mips64 -mcpu=mips64r6 -asm-show-inst < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1 -check-prefix=R6
+
+define void @ret_void() {
+; ALL-LABEL: ret_void:
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret void
+}
+
+define i8 @ret_i8() {
+; ALL-LABEL: ret_i8:
+; ALL-DAG: addiu $2, $zero, 3
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i8 3
+}
+
+define i16 @ret_i16_3() {
+; ALL-LABEL: ret_i16_3:
+; ALL-DAG: addiu $2, $zero, 3
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i16 3
+}
+
+define i16 @ret_i16_256() {
+; ALL-LABEL: ret_i16_256:
+; ALL-DAG: addiu $2, $zero, 256
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i16 256
+}
+
+define i16 @ret_i16_257() {
+; ALL-LABEL: ret_i16_257:
+; ALL-DAG: addiu $2, $zero, 257
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i16 257
+}
+
+define i32 @ret_i32_257() {
+; ALL-LABEL: ret_i32_257:
+; ALL-DAG: addiu $2, $zero, 257
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i32 257
+}
+
+define i32 @ret_i32_65536() {
+; ALL-LABEL: ret_i32_65536:
+; ALL-DAG: lui $2, 1
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i32 65536
+}
+
+define i32 @ret_i32_65537() {
+; ALL-LABEL: ret_i32_65537:
+; ALL: lui $[[T0:[0-9]+]], 1
+; ALL-DAG: ori $2, $[[T0]], 1
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i32 65537
+}
+
+define i64 @ret_i64_65537() {
+; ALL-LABEL: ret_i64_65537:
+; ALL: lui $[[T0:[0-9]+]], 1
+
+; GPR32-DAG: ori $3, $[[T0]], 1
+; GPR32-DAG: addiu $2, $zero, 0
+
+; GPR64-DAG: daddiu $2, $[[T0]], 1
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i64 65537
+}
+
+define i64 @ret_i64_281479271677952() {
+; ALL-LABEL: ret_i64_281479271677952:
+; ALL-DAG: lui $[[T0:[0-9]+]], 1
+
+; GPR32-DAG: ori $2, $[[T0]], 1
+; GPR32-DAG: addiu $3, $zero, 0
+
+; GPR64-DAG: daddiu $[[T1:[0-9]+]], $[[T0]], 1
+; GPR64-DAG: dsll $2, $[[T1]], 32
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i64 281479271677952
+}
+
+define i64 @ret_i64_281479271809026() {
+; ALL-LABEL: ret_i64_281479271809026:
+; GPR32-DAG: lui $[[T0:[0-9]+]], 1
+; GPR32-DAG: lui $[[T1:[0-9]+]], 2
+; GPR32-DAG: ori $2, $[[T0]], 1
+; GPR32-DAG: ori $3, $[[T1]], 2
+
+; GPR64-DAG: ori $[[T0:[0-9]+]], $zero, 32769
+; GPR64-DAG: dsll $[[T1:[0-9]+]], $[[T0]], 16
+; GPR64-DAG: daddiu $[[T0:[0-9]+]], $[[T0]], -32767
+; GPR64-DAG: dsll $[[T1:[0-9]+]], $[[T0]], 17
+; GPR64-DAG: daddiu $2, $[[T1]], 2
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret i64 281479271809026
+}
+
+define float @ret_float_0x0() {
+; ALL-LABEL: ret_float_0x0:
+
+; NO-MTHC1-DAG: mtc1 $zero, $f0
+
+; MTHC1-DAG: mtc1 $zero, $f0
+
+; DMTC-DAG: dmtc1 $zero, $f0
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret float 0x0000000000000000
+}
+
+define float @ret_float_0x3() {
+; ALL-LABEL: ret_float_0x3:
+
+; Use a constant pool
+; O32-DAG: lwc1 $f0, %lo($CPI
+; N64-DAG: lwc1 $f0, %got_ofst($CPI
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+; float constants are written as double constants
+ ret float 0x36b8000000000000
+}
+
+define double @ret_double_0x0() {
+; ALL-LABEL: ret_double_0x0:
+
+; NO-MTHC1-DAG: mtc1 $zero, $f0
+; NO-MTHC1-DAG: mtc1 $zero, $f1
+
+; MTHC1-DAG: mtc1 $zero, $f0
+; MTHC1-DAG: mthc1 $zero, $f0
+
+; DMTC-DAG: dmtc1 $zero, $f0
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret double 0x0000000000000000
+}
+
+define double @ret_double_0x3() {
+; ALL-LABEL: ret_double_0x3:
+
+; Use a constant pool
+; O32-DAG: ldc1 $f0, %lo($CPI
+; N64-DAG: ldc1 $f0, %got_ofst($CPI
+
+; NOT-R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JR
+; R6-DAG: jr $ra # <MCInst #{{[0-9]+}} JALR
+
+ ret double 0x0000000000000003
+}