
Add three more special cases for loading registers with immediates. The first allows values in the range of [-255, 255] to be loaded with MOVEQ, even if the register is more than 8 bits and the sign extention is unwanted. This is done by loading the bitwise complement of the desired value, then performing a NOT instruction on the loaded register. This special case is only used when a simple MOVEQ cannot be used, and is only used for 32 bit data registers. Address registers cannot support MOVEQ, and the two-instruction sequence is no faster or smaller than a plain MOVE instruction when loading 16 bit immediates on the 68000, and likely slower for more sophisticated microarchitectures. However, the instruction sequence is both smaller and faster than the corresponding MOVE instruction for 32 bit register widths. The second special case is for zeroing address registers. This simply expands to subtracting a register with itself, consuming one instruction word rather than 2-3, with a small improvement in speed as well. The last special case is for assigning sign-extended 16-bit values to a full address register. This takes advantage of the fact that the movea.w instruction sign extends the output, permitting the immediate to be smaller. This is similar to using lea with a 16-bit address, which is not added in this patch as 16-bit absolute addressing is not yet implemented. This is a v2 submission of #90817. It also creates a 'Data' test directory to better align with the backend's tablegen layout.
130 lines
3.8 KiB
LLVM
130 lines
3.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -frame-pointer=all -mtriple=m68k %s -verify-machineinstrs -o - \
|
|
; RUN: | FileCheck --check-prefix=FP %s
|
|
|
|
; RUN: llc -frame-pointer=none -mtriple=m68k %s -verify-machineinstrs -o - \
|
|
; RUN: | FileCheck --check-prefix=NO-FP %s
|
|
|
|
define i32 @fib(i32 %a, i32 %b) {
|
|
; FP-LABEL: fib:
|
|
; FP: .cfi_startproc
|
|
; FP-NEXT: ; %bb.0: ; %entry
|
|
; FP-NEXT: link.w %a6, #-32
|
|
; FP-NEXT: .cfi_def_cfa_offset -8
|
|
; FP-NEXT: .cfi_offset %a6, -8
|
|
; FP-NEXT: .cfi_def_cfa_register %a6
|
|
; FP-NEXT: move.l (8,%a6), %d1
|
|
; FP-NEXT: move.l %d1, (-32,%a6)
|
|
; FP-NEXT: move.l (12,%a6), %d0
|
|
; FP-NEXT: add.l %d0, %d1
|
|
; FP-NEXT: move.l %d0, (-28,%a6)
|
|
; FP-NEXT: add.l %d1, %d0
|
|
; FP-NEXT: move.l %d1, (-24,%a6)
|
|
; FP-NEXT: add.l %d0, %d1
|
|
; FP-NEXT: move.l %d0, (-20,%a6)
|
|
; FP-NEXT: move.l %d1, (-16,%a6)
|
|
; FP-NEXT: add.l %d1, %d0
|
|
; FP-NEXT: move.l %d0, (-12,%a6)
|
|
; FP-NEXT: add.l %d0, %d1
|
|
; FP-NEXT: move.l %d1, (-8,%a6)
|
|
; FP-NEXT: add.l %d1, %d0
|
|
; FP-NEXT: move.l %d0, (-4,%a6)
|
|
; FP-NEXT: unlk %a6
|
|
; FP-NEXT: rts
|
|
;
|
|
; NO-FP-LABEL: fib:
|
|
; NO-FP: .cfi_startproc
|
|
; NO-FP-NEXT: ; %bb.0: ; %entry
|
|
; NO-FP-NEXT: suba.l #32, %sp
|
|
; NO-FP-NEXT: .cfi_def_cfa_offset -36
|
|
; NO-FP-NEXT: move.l (36,%sp), %d1
|
|
; NO-FP-NEXT: move.l %d1, (0,%sp)
|
|
; NO-FP-NEXT: move.l (40,%sp), %d0
|
|
; NO-FP-NEXT: add.l %d0, %d1
|
|
; NO-FP-NEXT: move.l %d0, (4,%sp)
|
|
; NO-FP-NEXT: add.l %d1, %d0
|
|
; NO-FP-NEXT: move.l %d1, (8,%sp)
|
|
; NO-FP-NEXT: add.l %d0, %d1
|
|
; NO-FP-NEXT: move.l %d0, (12,%sp)
|
|
; NO-FP-NEXT: move.l %d1, (16,%sp)
|
|
; NO-FP-NEXT: add.l %d1, %d0
|
|
; NO-FP-NEXT: move.l %d0, (20,%sp)
|
|
; NO-FP-NEXT: add.l %d0, %d1
|
|
; NO-FP-NEXT: move.l %d1, (24,%sp)
|
|
; NO-FP-NEXT: add.l %d1, %d0
|
|
; NO-FP-NEXT: move.l %d0, (28,%sp)
|
|
; NO-FP-NEXT: adda.l #32, %sp
|
|
; NO-FP-NEXT: rts
|
|
entry:
|
|
%arr = alloca [8 x i32], align 4
|
|
%s0 = getelementptr i32, ptr %arr, i32 0
|
|
%s1 = getelementptr i32, ptr %arr, i32 1
|
|
store i32 %a, ptr %s0
|
|
store i32 %b, ptr %s1
|
|
|
|
%ptr0 = getelementptr i32, ptr %arr, i32 0
|
|
%ptr1 = getelementptr i32, ptr %arr, i32 1
|
|
%ptr2 = getelementptr i32, ptr %arr, i32 2
|
|
%ptr3 = getelementptr i32, ptr %arr, i32 3
|
|
%ptr4 = getelementptr i32, ptr %arr, i32 4
|
|
%ptr5 = getelementptr i32, ptr %arr, i32 5
|
|
%ptr6 = getelementptr i32, ptr %arr, i32 6
|
|
%ptr7 = getelementptr i32, ptr %arr, i32 7
|
|
|
|
%res0 = load i32, ptr %ptr0
|
|
%res1 = load i32, ptr %ptr1
|
|
|
|
%res2 = add i32 %res0, %res1
|
|
store i32 %res2, ptr %ptr2
|
|
|
|
%res3 = add i32 %res1, %res2
|
|
store i32 %res3, ptr %ptr3
|
|
|
|
%res4 = add i32 %res2, %res3
|
|
store i32 %res4, ptr %ptr4
|
|
|
|
%res5 = add i32 %res3, %res4
|
|
store i32 %res5, ptr %ptr5
|
|
|
|
%res6 = add i32 %res4, %res5
|
|
store i32 %res6, ptr %ptr6
|
|
|
|
%res7 = add i32 %res5, %res6
|
|
store i32 %res7, ptr %ptr7
|
|
|
|
ret i32 %res7
|
|
}
|
|
|
|
define i32 @test_gep() {
|
|
; FP-LABEL: test_gep:
|
|
; FP: .cfi_startproc
|
|
; FP-NEXT: ; %bb.0: ; %entry
|
|
; FP-NEXT: link.w %a6, #-256
|
|
; FP-NEXT: .cfi_def_cfa_offset -8
|
|
; FP-NEXT: .cfi_offset %a6, -8
|
|
; FP-NEXT: .cfi_def_cfa_register %a6
|
|
; FP-NEXT: move.l #21, (-4,%a6)
|
|
; FP-NEXT: move.l #12, (-256,%a6)
|
|
; FP-NEXT: moveq #0, %d0
|
|
; FP-NEXT: unlk %a6
|
|
; FP-NEXT: rts
|
|
;
|
|
; NO-FP-LABEL: test_gep:
|
|
; NO-FP: .cfi_startproc
|
|
; NO-FP-NEXT: ; %bb.0: ; %entry
|
|
; NO-FP-NEXT: suba.l #256, %sp
|
|
; NO-FP-NEXT: .cfi_def_cfa_offset -260
|
|
; NO-FP-NEXT: move.l #21, (252,%sp)
|
|
; NO-FP-NEXT: move.l #12, (0,%sp)
|
|
; NO-FP-NEXT: moveq #0, %d0
|
|
; NO-FP-NEXT: adda.l #256, %sp
|
|
; NO-FP-NEXT: rts
|
|
entry:
|
|
%arr = alloca [8 x [8 x i32]]
|
|
%ptr1 = getelementptr [8 x i32], ptr %arr, i64 0, i64 0
|
|
store i32 12, ptr %ptr1
|
|
%ptr2 = getelementptr [8 x i32], ptr %arr, i64 7, i64 7
|
|
store i32 21, ptr %ptr2
|
|
ret i32 0
|
|
}
|