brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · 533761c Raw
200 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s3 4;; Perform tail call optimization for global address.5declare i32 @callee_tail(i32 %i)6define i32 @caller_tail(i32 %i) nounwind {7; CHECK-LABEL: caller_tail:8; CHECK:       # %bb.0: # %entry9; CHECK-NEXT:    pcaddu18i $t8, %call36(callee_tail)10; CHECK-NEXT:    jr $t811entry:12  %r = tail call i32 @callee_tail(i32 %i)13  ret i32 %r14}15 16;; Perform tail call optimization for external symbol.17;; Bytes copied should be large enough, otherwise the memcpy call would be optimized to multiple ld/st insns.18@dest = global [2 x i8] zeroinitializer19declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1)20define void @caller_extern(ptr %src) optsize {21; CHECK-LABEL: caller_extern:22; CHECK:       # %bb.0: # %entry23; CHECK-NEXT:    pcalau12i $a1, %got_pc_hi20(dest)24; CHECK-NEXT:    ld.d $a1, $a1, %got_pc_lo12(dest)25; CHECK-NEXT:    ori $a2, $zero, 3326; CHECK-NEXT:    move $a3, $a027; CHECK-NEXT:    move $a0, $a128; CHECK-NEXT:    move $a1, $a329; CHECK-NEXT:    pcaddu18i $t8, %call36(memcpy)30; CHECK-NEXT:    jr $t831entry:32  tail call void @llvm.memcpy.p0.p0.i32(ptr @dest, ptr %src, i32 33, i1 false)33  ret void34}35 36;; Perform indirect tail call optimization (for function pointer call).37declare void @callee_indirect1()38declare void @callee_indirect2()39define void @caller_indirect_tail(i32 %a) nounwind {40; CHECK-LABEL: caller_indirect_tail:41; CHECK:       # %bb.0: # %entry42; CHECK-NEXT:    pcalau12i $a1, %got_pc_hi20(callee_indirect2)43; CHECK-NEXT:    ld.d $a1, $a1, %got_pc_lo12(callee_indirect2)44; CHECK-NEXT:    pcalau12i $a2, %got_pc_hi20(callee_indirect1)45; CHECK-NEXT:    ld.d $a2, $a2, %got_pc_lo12(callee_indirect1)46; CHECK-NEXT:    addi.w $a0, $a0, 047; CHECK-NEXT:    sltui $a0, $a0, 148; CHECK-NEXT:    masknez $a1, $a1, $a049; CHECK-NEXT:    maskeqz $a0, $a2, $a050; CHECK-NEXT:    or $a0, $a0, $a151; CHECK-NEXT:    jr $a052entry:53  %tobool = icmp eq i32 %a, 054  %callee = select i1 %tobool, ptr @callee_indirect1, ptr @callee_indirect255  tail call void %callee()56  ret void57}58 59;; Do not tail call optimize functions with varargs passed by stack.60declare i32 @callee_varargs(i32, ...)61define void @caller_varargs(i32 %a, i32 %b) nounwind {62; CHECK-LABEL: caller_varargs:63; CHECK:       # %bb.0: # %entry64; CHECK-NEXT:    addi.d $sp, $sp, -1665; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill66; CHECK-NEXT:    st.d $a0, $sp, 067; CHECK-NEXT:    move $a2, $a168; CHECK-NEXT:    move $a3, $a069; CHECK-NEXT:    move $a4, $a070; CHECK-NEXT:    move $a5, $a171; CHECK-NEXT:    move $a6, $a172; CHECK-NEXT:    move $a7, $a073; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_varargs)74; CHECK-NEXT:    jirl $ra, $ra, 075; CHECK-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload76; CHECK-NEXT:    addi.d $sp, $sp, 1677; CHECK-NEXT:    ret78entry:79  %call = tail call i32 (i32, ...) @callee_varargs(i32 %a, i32 %b, i32 %b, i32 %a, i32 %a, i32 %b, i32 %b, i32 %a, i32 %a)80  ret void81}82 83;; Do not tail call optimize if stack is used to pass parameters.84declare i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i)85define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i) nounwind {86; CHECK-LABEL: caller_args:87; CHECK:       # %bb.0: # %entry88; CHECK-NEXT:    addi.d $sp, $sp, -1689; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill90; CHECK-NEXT:    ld.d $t0, $sp, 1691; CHECK-NEXT:    st.d $t0, $sp, 092; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_args)93; CHECK-NEXT:    jirl $ra, $ra, 094; CHECK-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload95; CHECK-NEXT:    addi.d $sp, $sp, 1696; CHECK-NEXT:    ret97entry:98  %r = tail call i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i)99  ret i32 %r100}101 102;; Do not tail call optimize if parameters need to be passed indirectly.103declare i32 @callee_indirect_args(i256 %a)104define void @caller_indirect_args() nounwind {105; CHECK-LABEL: caller_indirect_args:106; CHECK:       # %bb.0: # %entry107; CHECK-NEXT:    addi.d $sp, $sp, -48108; CHECK-NEXT:    st.d $ra, $sp, 40 # 8-byte Folded Spill109; CHECK-NEXT:    st.d $zero, $sp, 24110; CHECK-NEXT:    vrepli.b $vr0, 0111; CHECK-NEXT:    vst $vr0, $sp, 8112; CHECK-NEXT:    ori $a1, $zero, 1113; CHECK-NEXT:    addi.d $a0, $sp, 0114; CHECK-NEXT:    st.d $a1, $sp, 0115; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_indirect_args)116; CHECK-NEXT:    jirl $ra, $ra, 0117; CHECK-NEXT:    ld.d $ra, $sp, 40 # 8-byte Folded Reload118; CHECK-NEXT:    addi.d $sp, $sp, 48119; CHECK-NEXT:    ret120entry:121  %call = tail call i32 @callee_indirect_args(i256 1)122  ret void123}124 125;; Do not tail call optimize if byval parameters need to be passed.126declare i32 @callee_byval(ptr byval(ptr) %a)127define i32 @caller_byval() nounwind {128; CHECK-LABEL: caller_byval:129; CHECK:       # %bb.0: # %entry130; CHECK-NEXT:    addi.d $sp, $sp, -32131; CHECK-NEXT:    st.d $ra, $sp, 24 # 8-byte Folded Spill132; CHECK-NEXT:    ld.d $a0, $sp, 16133; CHECK-NEXT:    st.d $a0, $sp, 8134; CHECK-NEXT:    addi.d $a0, $sp, 8135; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_byval)136; CHECK-NEXT:    jirl $ra, $ra, 0137; CHECK-NEXT:    ld.d $ra, $sp, 24 # 8-byte Folded Reload138; CHECK-NEXT:    addi.d $sp, $sp, 32139; CHECK-NEXT:    ret140entry:141  %a = alloca ptr142  %r = tail call i32 @callee_byval(ptr byval(ptr) %a)143  ret i32 %r144}145 146;; Do not tail call optimize if callee uses structret semantics.147%struct.A = type { i32 }148@a = global %struct.A zeroinitializer149 150declare void @callee_struct(ptr sret(%struct.A) %a)151define void @caller_nostruct() nounwind {152; CHECK-LABEL: caller_nostruct:153; CHECK:       # %bb.0: # %entry154; CHECK-NEXT:    addi.d $sp, $sp, -16155; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill156; CHECK-NEXT:    pcalau12i $a0, %got_pc_hi20(a)157; CHECK-NEXT:    ld.d $a0, $a0, %got_pc_lo12(a)158; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_struct)159; CHECK-NEXT:    jirl $ra, $ra, 0160; CHECK-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload161; CHECK-NEXT:    addi.d $sp, $sp, 16162; CHECK-NEXT:    ret163entry:164  tail call void @callee_struct(ptr sret(%struct.A) @a)165  ret void166}167 168;; Do not tail call optimize if caller uses structret semantics.169declare void @callee_nostruct()170define void @caller_struct(ptr sret(%struct.A) %a) nounwind {171; CHECK-LABEL: caller_struct:172; CHECK:       # %bb.0: # %entry173; CHECK-NEXT:    addi.d $sp, $sp, -16174; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill175; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_nostruct)176; CHECK-NEXT:    jirl $ra, $ra, 0177; CHECK-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload178; CHECK-NEXT:    addi.d $sp, $sp, 16179; CHECK-NEXT:    ret180entry:181  tail call void @callee_nostruct()182  ret void183}184 185;; Do not tail call optimize if disabled.186define i32 @disable_tail_calls(i32 %i) nounwind "disable-tail-calls"="true" {187; CHECK-LABEL: disable_tail_calls:188; CHECK:       # %bb.0: # %entry189; CHECK-NEXT:    addi.d $sp, $sp, -16190; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill191; CHECK-NEXT:    pcaddu18i $ra, %call36(callee_tail)192; CHECK-NEXT:    jirl $ra, $ra, 0193; CHECK-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload194; CHECK-NEXT:    addi.d $sp, $sp, 16195; CHECK-NEXT:    ret196entry:197  %rv = tail call i32 @callee_tail(i32 %i)198  ret i32 %rv199}200