blob: 40905384799e632e5633512267f26233729fbdec [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=loongarch64 -mattr=+ual -O2 -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=loongarch64 -mattr=+ual -O2 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=+ual -O0 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=+ual -O1 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=+ual -O3 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=-ual -O0 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=-ual -O1 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=-ual -O2 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
; RUN: llc -mtriple=loongarch64 -mattr=-ual -O3 -verify-machineinstrs < %s | llvm-mc -triple=loongarch64 -filetype=obj -o %t.o
;
; The displacement 2048 fits si14 << 2 during instruction selection. The
; byte-aligned stack object makes the final FP-relative displacement -977,
; which is not a multiple of four. Frame index elimination must fall back
; to the corresponding unscaled load/store without changing the address.
;
; Keep the assembly round-trip: MachineVerifier alone does not diagnose
; every target-specific immediate constraint, and an MC encoder must not
; silently discard the low two offset bits.
; Reviewer reproducer: the i32 load is promoted to an any-extending load.
define i32 @anyext_frame_offset() "frame-pointer"="all" nounwind {
; CHECK-LABEL: anyext_frame_offset:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: addi.d $sp, $sp, -2032
; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill
; CHECK-NEXT: st.d $fp, $sp, 2016 # 8-byte Folded Spill
; CHECK-NEXT: addi.d $fp, $sp, 2032
; CHECK-NEXT: addi.d $sp, $sp, -1008
; CHECK-NEXT: lu12i.w $a0, -1
; CHECK-NEXT: ori $a0, $a0, 1071
; CHECK-NEXT: add.d $a0, $fp, $a0
; CHECK-NEXT: pcaddu18i $ra, %call36(use)
; CHECK-NEXT: jirl $ra, $ra, 0
; CHECK-NEXT: ld.w $a0, $fp, -977
; CHECK-NEXT: addi.d $sp, $sp, 1008
; CHECK-NEXT: ld.d $fp, $sp, 2016 # 8-byte Folded Reload
; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 2032
; CHECK-NEXT: ret
entry:
%a = alloca [3001 x i8], align 1
call void @use(ptr %a)
%p = getelementptr i8, ptr %a, i64 2048
%v = load i32, ptr %p, align 1
ret i32 %v
}
; The pre-existing sign-extending pattern needs the same final-offset check.
define i64 @sext_frame_offset() "frame-pointer"="all" nounwind {
; CHECK-LABEL: sext_frame_offset:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: addi.d $sp, $sp, -2032
; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill
; CHECK-NEXT: st.d $fp, $sp, 2016 # 8-byte Folded Spill
; CHECK-NEXT: addi.d $fp, $sp, 2032
; CHECK-NEXT: addi.d $sp, $sp, -1008
; CHECK-NEXT: lu12i.w $a0, -1
; CHECK-NEXT: ori $a0, $a0, 1071
; CHECK-NEXT: add.d $a0, $fp, $a0
; CHECK-NEXT: pcaddu18i $ra, %call36(use)
; CHECK-NEXT: jirl $ra, $ra, 0
; CHECK-NEXT: ld.w $a0, $fp, -977
; CHECK-NEXT: addi.d $sp, $sp, 1008
; CHECK-NEXT: ld.d $fp, $sp, 2016 # 8-byte Folded Reload
; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 2032
; CHECK-NEXT: ret
entry:
%a = alloca [3001 x i8], align 1
call void @use(ptr %a)
%p = getelementptr i8, ptr %a, i64 2048
%v = load i32, ptr %p, align 1
%ext = sext i32 %v to i64
ret i64 %ext
}
define i64 @load64_frame_offset() "frame-pointer"="all" nounwind {
; CHECK-LABEL: load64_frame_offset:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: addi.d $sp, $sp, -2032
; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill
; CHECK-NEXT: st.d $fp, $sp, 2016 # 8-byte Folded Spill
; CHECK-NEXT: addi.d $fp, $sp, 2032
; CHECK-NEXT: addi.d $sp, $sp, -1008
; CHECK-NEXT: lu12i.w $a0, -1
; CHECK-NEXT: ori $a0, $a0, 1071
; CHECK-NEXT: add.d $a0, $fp, $a0
; CHECK-NEXT: pcaddu18i $ra, %call36(use)
; CHECK-NEXT: jirl $ra, $ra, 0
; CHECK-NEXT: ld.d $a0, $fp, -977
; CHECK-NEXT: addi.d $sp, $sp, 1008
; CHECK-NEXT: ld.d $fp, $sp, 2016 # 8-byte Folded Reload
; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 2032
; CHECK-NEXT: ret
entry:
%a = alloca [3001 x i8], align 1
call void @use(ptr %a)
%p = getelementptr i8, ptr %a, i64 2048
%v = load i64, ptr %p, align 1
ret i64 %v
}
; Use a constant stored value so no extra callee-saved register changes
; the stack layout. Volatile keeps the store to the local object alive.
define void @store32_frame_offset() "frame-pointer"="all" nounwind {
; CHECK-LABEL: store32_frame_offset:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: addi.d $sp, $sp, -2032
; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill
; CHECK-NEXT: st.d $fp, $sp, 2016 # 8-byte Folded Spill
; CHECK-NEXT: addi.d $fp, $sp, 2032
; CHECK-NEXT: addi.d $sp, $sp, -1008
; CHECK-NEXT: lu12i.w $a0, -1
; CHECK-NEXT: ori $a0, $a0, 1071
; CHECK-NEXT: add.d $a0, $fp, $a0
; CHECK-NEXT: pcaddu18i $ra, %call36(use)
; CHECK-NEXT: jirl $ra, $ra, 0
; CHECK-NEXT: st.w $zero, $fp, -977
; CHECK-NEXT: addi.d $sp, $sp, 1008
; CHECK-NEXT: ld.d $fp, $sp, 2016 # 8-byte Folded Reload
; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 2032
; CHECK-NEXT: ret
entry:
%a = alloca [3001 x i8], align 1
call void @use(ptr %a)
%p = getelementptr i8, ptr %a, i64 2048
store volatile i32 0, ptr %p, align 1
ret void
}
define void @store64_frame_offset() "frame-pointer"="all" nounwind {
; CHECK-LABEL: store64_frame_offset:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: addi.d $sp, $sp, -2032
; CHECK-NEXT: st.d $ra, $sp, 2024 # 8-byte Folded Spill
; CHECK-NEXT: st.d $fp, $sp, 2016 # 8-byte Folded Spill
; CHECK-NEXT: addi.d $fp, $sp, 2032
; CHECK-NEXT: addi.d $sp, $sp, -1008
; CHECK-NEXT: lu12i.w $a0, -1
; CHECK-NEXT: ori $a0, $a0, 1071
; CHECK-NEXT: add.d $a0, $fp, $a0
; CHECK-NEXT: pcaddu18i $ra, %call36(use)
; CHECK-NEXT: jirl $ra, $ra, 0
; CHECK-NEXT: st.d $zero, $fp, -977
; CHECK-NEXT: addi.d $sp, $sp, 1008
; CHECK-NEXT: ld.d $fp, $sp, 2016 # 8-byte Folded Reload
; CHECK-NEXT: ld.d $ra, $sp, 2024 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 2032
; CHECK-NEXT: ret
entry:
%a = alloca [3001 x i8], align 1
call void @use(ptr %a)
%p = getelementptr i8, ptr %a, i64 2048
store volatile i64 0, ptr %p, align 1
ret void
}
declare void @use(ptr)