| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32 | |
| ; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64 | |
| ;; Check that stptr.w is not emitted for small offsets. | |
| define void @stptr_w_too_small_offset(ptr %p, i32 signext %val) nounwind { | |
| ; LA32-LABEL: stptr_w_too_small_offset: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: st.w $a1, $a0, 2044 | |
| ; LA32-NEXT: ret | |
| ; | |
| ; LA64-LABEL: stptr_w_too_small_offset: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: st.w $a1, $a0, 2044 | |
| ; LA64-NEXT: ret | |
| %addr = getelementptr inbounds i32, ptr %p, i64 511 | |
| store i32 %val, ptr %addr, align 4 | |
| ret void | |
| } | |
| ;; Check that stptr.w is emitted for applicable offsets. | |
| define void @stptr_w(ptr %p, i32 signext %val) nounwind { | |
| ; LA32-LABEL: stptr_w: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: addi.w $a0, $a0, 2047 | |
| ; LA32-NEXT: st.w $a1, $a0, 1 | |
| ; LA32-NEXT: ret | |
| ; | |
| ; LA64-LABEL: stptr_w: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: stptr.w $a1, $a0, 2048 | |
| ; LA64-NEXT: ret | |
| %addr = getelementptr inbounds i32, ptr %p, i64 512 | |
| store i32 %val, ptr %addr, align 4 | |
| ret void | |
| } | |
| ;; Check that stptr.w is not emitted for out-of-range offsets. | |
| define void @stptr_w_too_big_offset(ptr %p, i32 signext %val) nounwind { | |
| ; LA32-LABEL: stptr_w_too_big_offset: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: lu12i.w $a2, 8 | |
| ; LA32-NEXT: add.w $a0, $a0, $a2 | |
| ; LA32-NEXT: st.w $a1, $a0, 0 | |
| ; LA32-NEXT: ret | |
| ; | |
| ; LA64-LABEL: stptr_w_too_big_offset: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: lu12i.w $a2, 8 | |
| ; LA64-NEXT: stx.w $a1, $a0, $a2 | |
| ; LA64-NEXT: ret | |
| %addr = getelementptr inbounds i32, ptr %p, i64 8192 | |
| store i32 %val, ptr %addr, align 4 | |
| ret void | |
| } | |
| ;; Check that stptr.d is not emitted for small offsets. | |
| define void @stptr_d_too_small_offset(ptr %p, i64 %val) nounwind { | |
| ; LA32-LABEL: stptr_d_too_small_offset: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: st.w $a2, $a0, 2044 | |
| ; LA32-NEXT: st.w $a1, $a0, 2040 | |
| ; LA32-NEXT: ret | |
| ; | |
| ; LA64-LABEL: stptr_d_too_small_offset: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: st.d $a1, $a0, 2040 | |
| ; LA64-NEXT: ret | |
| %addr = getelementptr inbounds i64, ptr %p, i64 255 | |
| store i64 %val, ptr %addr, align 8 | |
| ret void | |
| } | |
| ;; Check that stptr.d is emitted for applicable offsets. | |
| define void @stptr_d(ptr %p, i64 %val) nounwind { | |
| ; LA32-LABEL: stptr_d: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: addi.w $a0, $a0, 2047 | |
| ; LA32-NEXT: st.w $a2, $a0, 5 | |
| ; LA32-NEXT: st.w $a1, $a0, 1 | |
| ; LA32-NEXT: ret | |
| ; | |
| ; LA64-LABEL: stptr_d: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: stptr.d $a1, $a0, 2048 | |
| ; LA64-NEXT: ret | |
| %addr = getelementptr inbounds i64, ptr %p, i64 256 | |
| store i64 %val, ptr %addr, align 8 | |
| ret void | |
| } | |
| ;; Check that stptr.d is not emitted for out-of-range offsets. | |
| define void @stptr_d_too_big_offset(ptr %p, i64 %val) nounwind { | |
| ; LA32-LABEL: stptr_d_too_big_offset: | |
| ; LA32: # %bb.0: | |
| ; LA32-NEXT: lu12i.w $a3, 8 | |
| ; LA32-NEXT: add.w $a0, $a0, $a3 | |
| ; LA32-NEXT: st.w $a2, $a0, 4 | |
| ; LA32-NEXT: st.w $a1, $a0, 0 | |
| ; LA32-NEXT: ret | |
| ; | |
| ; LA64-LABEL: stptr_d_too_big_offset: | |
| ; LA64: # %bb.0: | |
| ; LA64-NEXT: lu12i.w $a2, 8 | |
| ; LA64-NEXT: stx.d $a1, $a0, $a2 | |
| ; LA64-NEXT: ret | |
| %addr = getelementptr inbounds i64, ptr %p, i64 4096 | |
| store i64 %val, ptr %addr, align 8 | |
| ret void | |
| } |