blob: c93ef7c0d651dc70afa0adfd4eb246000d23deef [file] [edit]
; RUN: llc -mtriple=avr -mcpu=atmega328 -O1 -verify-machineinstrs < %s | FileCheck %s
declare void @use(ptr %x);
; Case: One 2-byte variable with alignment of 1.
;
; This shouldn't activate stack realignment - this function exists so that it's
; easy to see the difference when stack realignment gets actually activated (see
; the next test case).
define i16 @no_alignment() {
; CHECK-LABEL: no_alignment:
; CHECK-NEXT: ; %bb.0:
;
;; prologue
; CHECK-NEXT: push r28
; CHECK-NEXT: push r29
; CHECK-NEXT: in r28, 61
; CHECK-NEXT: in r29, 62
; CHECK-NEXT: sbiw r28, 2
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
;
;; call void @use(ptr %1)
; CHECK-NEXT: movw r24, r28
; CHECK-NEXT: adiw r24, 1
; CHECK-NEXT: call use
;
;; %2 = load i16, ptr %1, align 1
; CHECK-NEXT: ldd r24, Y+1
; CHECK-NEXT: ldd r25, Y+2
;
;; epilogue
; CHECK-NEXT: adiw r28, 2
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
; CHECK-NEXT: pop r29
; CHECK-NEXT: pop r28
; CHECK-NEXT: ret
%1 = alloca i16, align 1
call void @use(ptr %1)
%2 = load i16, ptr %1, align 1
ret i16 %2
}
; Case: One 2-byte variable with alignment of 16.
;
; This reserves 2 + 16 - 1 = 17 bytes of stack space and allocates an extra
; aligned stack pointer (in this case into r24:r25).
define i16 @some_alignment() {
; CHECK-LABEL: some_alignment:
; CHECK-NEXT: %bb.0:
;
;; prologue
; CHECK-NEXT: push r16
; CHECK-NEXT: push r17
; CHECK-NEXT: push r28
; CHECK-NEXT: push r29
; CHECK-NEXT: in r28, 61
; CHECK-NEXT: in r29, 62
; CHECK-NEXT: sbiw r28, 17
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
;
;; SP allocation
; CHECK-NEXT: movw r24, r28
; CHECK-NEXT: adiw r24, 16
; CHECK-NEXT: andi r24, 240
;
;; call void @use (ptr %1)
; CHECK-NEXT: movw r16, r24
; CHECK-NEXT: movw r24, r16
; CHECK-NEXT: call use
;
;; %2 = load i16, ptr %1, align 16
; CHECK-NEXT: movw r30, r16
; CHECK-NEXT: ld r24, Z
; CHECK-NEXT: ldd r25, Z+1
;
;; epilogue
; CHECK-NEXT: adiw r28, 17
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
; CHECK-NEXT: pop r29
; CHECK-NEXT: pop r28
; CHECK-NEXT: pop r17
; CHECK-NEXT: pop r16
; CHECK-NEXT: ret
%1 = alloca i16, align 16
call void @use(ptr %1)
%2 = load i16, ptr %1, align 16
ret i16 %2
}
; Case: One variable with no alignment, another variable with alignment of 16.
;
; This creates two separate stack spaces - an unaligned one (r28:r29) and an
; aligned one (r16:r17).
define i16 @mixed_alignment() {
; CHECK-LABEL: mixed_alignment:
; CHECK-NEXT: ; %bb.0:
;
;; prologue
; CHECK-NEXT: push r16
; CHECK-NEXT: push r17
; CHECK-NEXT: push r28
; CHECK-NEXT: push r29
; CHECK-NEXT: in r28, 61
; CHECK-NEXT: in r29, 62
; CHECK-NEXT: sbiw r28, 19
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
;
;; SP allocation
; CHECK-NEXT: movw r16, r28
; CHECK-NEXT: subi r16, 238
; CHECK-NEXT: sbci r17, 255
; CHECK-NEXT: andi r16, 240
;
;; call void @use(ptr %1)
; CHECK-NEXT: movw r24, r28
; CHECK-NEXT: adiw r24, 1
; CHECK-NEXT: call use
;
;; call void @use(ptr %2)
; CHECK-NEXT: movw r24, r16
; CHECK-NEXT: call use
;
;; %4 = load i16, ptr %2, align 16
; CHECK-NEXT: movw r30, r16
; CHECK-NEXT: ld r18, Z
; CHECK-NEXT: ldd r19, Z+1
;
;; %3 = load i16, ptr %1, align 1
; CHECK-NEXT: ldd r24, Y+1
; CHECK-NEXT: ldd r25, Y+2
;
;; %5 = or i16 %3, %4
; CHECK-NEXT: or r24, r18
; CHECK-NEXT: or r25, r19
;
;; epilogue
; CHECK-NEXT: adiw r28, 19
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
; CHECK-NEXT: pop r29
; CHECK-NEXT: pop r28
; CHECK-NEXT: pop r17
; CHECK-NEXT: pop r16
; CHECK-NEXT: ret
%1 = alloca i16, align 1
%2 = alloca i16, align 16
call void @use(ptr %1)
call void @use(ptr %2)
%3 = load i16, ptr %1, align 1
%4 = load i16, ptr %2, align 16
%5 = or i16 %3, %4
ret i16 %5
}
; Case: getelementptr referring to an aligned variable.
define i16 @gep() {
; CHECK-LABEL: gep:
; CHECK-NEXT: ; %bb.0:
;
;; prologue
; CHECK-NEXT: push r16
; CHECK-NEXT: push r17
; CHECK-NEXT: push r28
; CHECK-NEXT: push r29
; CHECK-NEXT: in r28, 61
; CHECK-NEXT: in r29, 62
; CHECK-NEXT: sbiw r28, 23
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
;
;; SP allocation
; CHECK-NEXT: movw r16, r28
; CHECK-NEXT: subi r16, 248
; CHECK-NEXT: sbci r17, 255
; CHECK-NEXT: andi r16, 248
;
;; %2 = getelementptr inbounds nuw i8, ptr %1, i16 8
; CHECK-NEXT: movw r24, r16
; CHECK-NEXT: adiw r24, 8
;
;; call void @use(ptr %2)
; CHECK-NEXT: call use
;
;; %3 = getelementptr inbounds nuw i8, ptr %1, i16 8
; CHECK-NEXT: movw r24, r16
; CHECK-NEXT: adiw r24, 8
;
;; %4 = load i16, ptr %3, align 4
;; ret i16 %4
; CHECK-NEXT: movw r30, r24
; CHECK-NEXT: ld r24, Z
; CHECK-NEXT: ldd r25, Z+1
; CHECK-NEXT: adiw r28, 23
;
;; epilogue
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: out 62, r29
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: out 61, r28
; CHECK-NEXT: pop r29
; CHECK-NEXT: pop r28
; CHECK-NEXT: pop r17
; CHECK-NEXT: pop r16
; CHECK-NEXT: ret
%1 = alloca [8 x i16], align 8
%2 = getelementptr inbounds nuw i8, ptr %1, i16 8
call void @use(ptr %2)
%3 = getelementptr inbounds nuw i8, ptr %1, i16 8
%4 = load i16, ptr %3, align 4
ret i16 %4
}