Files
clang-p2996/llvm/test/CodeGen/LoongArch/code-models.ll
hev f7a96dc664 [LoongArch] Ensure pcaddu18i and jirl adjacency in tail calls for correct relocation (#113932)
Prior to this patch, both `pcaddu18i` and `jirl` were marked as
scheduling boundaries to prevent instruction reordering that would
disrupt their adjacency. However, in certain cases, epilogues were still
being inserted between these two instructions, breaking the required
proximity. This patch ensures that `pcaddu18i` and `jirl` remain
adjacent even in the presence of epilogues, maintaining correct
relocation behavior for tail calls on LoongArch.
2024-11-01 00:08:15 +08:00

123 lines
4.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=small < %s | \
; RUN: FileCheck --check-prefix=SMALL %s
; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=medium < %s | \
; RUN: FileCheck --check-prefix=MEDIUM %s
; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large < %s | \
; RUN: FileCheck --check-prefix=LARGE %s
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
declare i32 @callee(i32)
define i32 @call_globaladdress(i32 %a) nounwind {
; SMALL-LABEL: call_globaladdress:
; SMALL: # %bb.0:
; SMALL-NEXT: addi.d $sp, $sp, -16
; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; SMALL-NEXT: bl %plt(callee)
; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; SMALL-NEXT: addi.d $sp, $sp, 16
; SMALL-NEXT: ret
;
; MEDIUM-LABEL: call_globaladdress:
; MEDIUM: # %bb.0:
; MEDIUM-NEXT: addi.d $sp, $sp, -16
; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; MEDIUM-NEXT: pcaddu18i $ra, %call36(callee)
; MEDIUM-NEXT: jirl $ra, $ra, 0
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; MEDIUM-NEXT: addi.d $sp, $sp, 16
; MEDIUM-NEXT: ret
;
; LARGE-LABEL: call_globaladdress:
; LARGE: # %bb.0:
; LARGE-NEXT: addi.d $sp, $sp, -16
; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee)
; LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(callee)
; LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(callee)
; LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(callee)
; LARGE-NEXT: ldx.d $ra, $ra, $a1
; LARGE-NEXT: jirl $ra, $ra, 0
; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LARGE-NEXT: addi.d $sp, $sp, 16
; LARGE-NEXT: ret
%1 = call i32 @callee(i32 %a)
ret i32 %1
}
define void @call_external_sym(ptr %dst) {
; SMALL-LABEL: call_external_sym:
; SMALL: # %bb.0: # %entry
; SMALL-NEXT: addi.d $sp, $sp, -16
; SMALL-NEXT: .cfi_def_cfa_offset 16
; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; SMALL-NEXT: .cfi_offset 1, -8
; SMALL-NEXT: ori $a2, $zero, 1000
; SMALL-NEXT: move $a1, $zero
; SMALL-NEXT: bl %plt(memset)
; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; SMALL-NEXT: addi.d $sp, $sp, 16
; SMALL-NEXT: ret
;
; MEDIUM-LABEL: call_external_sym:
; MEDIUM: # %bb.0: # %entry
; MEDIUM-NEXT: addi.d $sp, $sp, -16
; MEDIUM-NEXT: .cfi_def_cfa_offset 16
; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; MEDIUM-NEXT: .cfi_offset 1, -8
; MEDIUM-NEXT: ori $a2, $zero, 1000
; MEDIUM-NEXT: move $a1, $zero
; MEDIUM-NEXT: pcaddu18i $ra, %call36(memset)
; MEDIUM-NEXT: jirl $ra, $ra, 0
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; MEDIUM-NEXT: addi.d $sp, $sp, 16
; MEDIUM-NEXT: ret
;
; LARGE-LABEL: call_external_sym:
; LARGE: # %bb.0: # %entry
; LARGE-NEXT: addi.d $sp, $sp, -16
; LARGE-NEXT: .cfi_def_cfa_offset 16
; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LARGE-NEXT: .cfi_offset 1, -8
; LARGE-NEXT: ori $a2, $zero, 1000
; LARGE-NEXT: move $a1, $zero
; LARGE-NEXT: pcalau12i $a3, %pc_hi20(memset)
; LARGE-NEXT: addi.d $ra, $zero, %pc_lo12(memset)
; LARGE-NEXT: lu32i.d $ra, %pc64_lo20(memset)
; LARGE-NEXT: lu52i.d $ra, $ra, %pc64_hi12(memset)
; LARGE-NEXT: add.d $ra, $ra, $a3
; LARGE-NEXT: jirl $ra, $ra, 0
; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LARGE-NEXT: addi.d $sp, $sp, 16
; LARGE-NEXT: ret
entry:
call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 1000, i1 false)
ret void
}
;; Tail call with different codemodel.
declare i32 @callee_tail(i32 %i)
define i32 @caller_tail(i32 %i) nounwind {
; SMALL-LABEL: caller_tail:
; SMALL: # %bb.0: # %entry
; SMALL-NEXT: b %plt(callee_tail)
;
; MEDIUM-LABEL: caller_tail:
; MEDIUM: # %bb.0: # %entry
; MEDIUM-NEXT: pcaddu18i $t8, %call36(callee_tail)
; MEDIUM-NEXT: jr $t8
;
; LARGE-LABEL: caller_tail:
; LARGE: # %bb.0: # %entry
; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee_tail)
; LARGE-NEXT: addi.d $a2, $zero, %got_pc_lo12(callee_tail)
; LARGE-NEXT: lu32i.d $a2, %got64_pc_lo20(callee_tail)
; LARGE-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(callee_tail)
; LARGE-NEXT: ldx.d $a1, $a2, $a1
; LARGE-NEXT: jr $a1
entry:
%r = tail call i32 @callee_tail(i32 %i)
ret i32 %r
}