The 'ELPM' instruction has three forms: -------------------------- | form | feature | | ----------- | -------- | | ELPM | hasELPM | | ELPM Rd, Z | hasELPMX | | ELPM Rd, Z+ | hasELPMX | -------------------------- The second form is always used in the expansion of the pseudo instruction 'ELPMBRdZ'. But for devices without ELPMX but only with ELPM, only the first form can be emitted. Reviewed By: jacquesguan Differential Revision: https://reviews.llvm.org/D141221
317 lines
10 KiB
LLVM
317 lines
10 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=avr -mattr=+movw -mattr=+elpm -mattr=+elpmx -mattr=+lpm -mattr=+lpmx -verify-machineinstrs \
|
|
; RUN: | FileCheck %s
|
|
; RUN: llc < %s -mtriple=avr -mattr=+movw -mattr=+elpm -mattr=-elpmx -mattr=+lpm -mattr=-lpmx -verify-machineinstrs \
|
|
; RUN: | FileCheck --check-prefix=NOX %s
|
|
|
|
@arr0 = addrspace(1) constant [4 x i16] [i16 123, i16 24, i16 56, i16 37], align 1
|
|
@arr1 = addrspace(2) constant [4 x i16] [i16 123, i16 34, i16 46, i16 27], align 1
|
|
@arr2 = addrspace(3) constant [4 x i16] [i16 123, i16 23, i16 45, i16 17], align 1
|
|
|
|
define i16 @foo0(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foo0:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: lsl r22
|
|
; CHECK-NEXT: rol r23
|
|
; CHECK-NEXT: subi r22, lo8(-(arr0))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arr0))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: lpm r18, Z+
|
|
; CHECK-NEXT: lpm r19, Z
|
|
; CHECK-NEXT: lsl r24
|
|
; CHECK-NEXT: rol r25
|
|
; CHECK-NEXT: subi r24, lo8(-(arr0))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arr0))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: lpm r24, Z+
|
|
; CHECK-NEXT: lpm r25, Z
|
|
; CHECK-NEXT: sub r24, r18
|
|
; CHECK-NEXT: sbc r25, r19
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i16], [4 x i16] addrspace(1)* @arr0, i16 0, i16 %a
|
|
%0 = load i16, i16 addrspace(1)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i16], [4 x i16] addrspace(1)* @arr0, i16 0, i16 %b
|
|
%1 = load i16, i16 addrspace(1)* %arrayidx1, align 1
|
|
%sub = sub nsw i16 %0, %1
|
|
ret i16 %sub
|
|
}
|
|
|
|
define i16 @foo1(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foo1:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: lsl r22
|
|
; CHECK-NEXT: rol r23
|
|
; CHECK-NEXT: subi r22, lo8(-(arr1))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arr1))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: ldi r18, 1
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r20, Z+
|
|
; CHECK-NEXT: elpm r21, Z
|
|
; CHECK-NEXT: lsl r24
|
|
; CHECK-NEXT: rol r25
|
|
; CHECK-NEXT: subi r24, lo8(-(arr0))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arr0))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: lpm r24, Z+
|
|
; CHECK-NEXT: lpm r25, Z
|
|
; CHECK-NEXT: sub r24, r20
|
|
; CHECK-NEXT: sbc r25, r21
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i16], [4 x i16] addrspace(1)* @arr0, i16 0, i16 %a
|
|
%0 = load i16, i16 addrspace(1)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i16], [4 x i16] addrspace(2)* @arr1, i16 0, i16 %b
|
|
%1 = load i16, i16 addrspace(2)* %arrayidx1, align 1
|
|
%sub = sub nsw i16 %0, %1
|
|
ret i16 %sub
|
|
}
|
|
|
|
define i16 @foo2(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foo2:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: lsl r24
|
|
; CHECK-NEXT: rol r25
|
|
; CHECK-NEXT: subi r24, lo8(-(arr2))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arr2))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: ldi r18, 2
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r24, Z+
|
|
; CHECK-NEXT: elpm r25, Z
|
|
; CHECK-NEXT: lsl r22
|
|
; CHECK-NEXT: rol r23
|
|
; CHECK-NEXT: subi r22, lo8(-(arr0))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arr0))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: lpm r18, Z+
|
|
; CHECK-NEXT: lpm r19, Z
|
|
; CHECK-NEXT: sub r24, r18
|
|
; CHECK-NEXT: sbc r25, r19
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i16], [4 x i16] addrspace(3)* @arr2, i16 0, i16 %a
|
|
%0 = load i16, i16 addrspace(3)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i16], [4 x i16] addrspace(1)* @arr0, i16 0, i16 %b
|
|
%1 = load i16, i16 addrspace(1)* %arrayidx1, align 1
|
|
%sub = sub nsw i16 %0, %1
|
|
ret i16 %sub
|
|
}
|
|
|
|
define i16 @foo3(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foo3:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: lsl r22
|
|
; CHECK-NEXT: rol r23
|
|
; CHECK-NEXT: subi r22, lo8(-(arr1))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arr1))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: ldi r18, 1
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r20, Z+
|
|
; CHECK-NEXT: elpm r21, Z
|
|
; CHECK-NEXT: lsl r24
|
|
; CHECK-NEXT: rol r25
|
|
; CHECK-NEXT: subi r24, lo8(-(arr2))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arr2))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: ldi r18, 2
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r24, Z+
|
|
; CHECK-NEXT: elpm r25, Z
|
|
; CHECK-NEXT: sub r24, r20
|
|
; CHECK-NEXT: sbc r25, r21
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i16], [4 x i16] addrspace(3)* @arr2, i16 0, i16 %a
|
|
%0 = load i16, i16 addrspace(3)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i16], [4 x i16] addrspace(2)* @arr1, i16 0, i16 %b
|
|
%1 = load i16, i16 addrspace(2)* %arrayidx1, align 1
|
|
%sub = sub nsw i16 %0, %1
|
|
ret i16 %sub
|
|
}
|
|
|
|
@arrb1 = addrspace(1) constant [4 x i8] c"abcd", align 1
|
|
@arrb3 = addrspace(3) constant [4 x i8] c"1234", align 1
|
|
@arrb5 = addrspace(5) constant [4 x i8] c"HJLQ", align 1
|
|
|
|
define signext i8 @foob0(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foob0:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: subi r22, lo8(-(arrb1))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arrb1))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: lpm r18, Z
|
|
; CHECK-NEXT: subi r24, lo8(-(arrb1))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arrb1))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: lpm r24, Z
|
|
; CHECK-NEXT: sub r24, r18
|
|
; CHECK-NEXT: mov r25, r24
|
|
; CHECK-NEXT: lsl r25
|
|
; CHECK-NEXT: sbc r25, r25
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i8], [4 x i8] addrspace(1)* @arrb1, i16 0, i16 %a
|
|
%0 = load i8, i8 addrspace(1)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i8], [4 x i8] addrspace(1)* @arrb1, i16 0, i16 %b
|
|
%1 = load i8, i8 addrspace(1)* %arrayidx1, align 1
|
|
%sub = sub i8 %0, %1
|
|
ret i8 %sub
|
|
}
|
|
|
|
define signext i8 @foob1(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foob1:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: subi r22, lo8(-(arrb3))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arrb3))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: ldi r18, 2
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r18, Z
|
|
; CHECK-NEXT: subi r24, lo8(-(arrb1))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arrb1))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: lpm r24, Z
|
|
; CHECK-NEXT: sub r24, r18
|
|
; CHECK-NEXT: mov r25, r24
|
|
; CHECK-NEXT: lsl r25
|
|
; CHECK-NEXT: sbc r25, r25
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i8], [4 x i8] addrspace(1)* @arrb1, i16 0, i16 %a
|
|
%0 = load i8, i8 addrspace(1)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i8], [4 x i8] addrspace(3)* @arrb3, i16 0, i16 %b
|
|
%1 = load i8, i8 addrspace(3)* %arrayidx1, align 1
|
|
%sub = sub i8 %0, %1
|
|
ret i8 %sub
|
|
}
|
|
|
|
define signext i8 @foob2(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foob2:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: subi r24, lo8(-(arrb5))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arrb5))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: ldi r24, 4
|
|
; CHECK-NEXT: out 59, r24
|
|
; CHECK-NEXT: elpm r24, Z
|
|
; CHECK-NEXT: subi r22, lo8(-(arrb1))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arrb1))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: lpm r25, Z
|
|
; CHECK-NEXT: sub r24, r25
|
|
; CHECK-NEXT: mov r25, r24
|
|
; CHECK-NEXT: lsl r25
|
|
; CHECK-NEXT: sbc r25, r25
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i8], [4 x i8] addrspace(5)* @arrb5, i16 0, i16 %a
|
|
%0 = load i8, i8 addrspace(5)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i8], [4 x i8] addrspace(1)* @arrb1, i16 0, i16 %b
|
|
%1 = load i8, i8 addrspace(1)* %arrayidx1, align 1
|
|
%sub = sub i8 %0, %1
|
|
ret i8 %sub
|
|
}
|
|
|
|
define signext i8 @foob3(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foob3:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: subi r22, lo8(-(arrb5))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arrb5))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: ldi r18, 4
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r18, Z
|
|
; CHECK-NEXT: subi r24, lo8(-(arrb3))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arrb3))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: ldi r24, 2
|
|
; CHECK-NEXT: out 59, r24
|
|
; CHECK-NEXT: elpm r24, Z
|
|
; CHECK-NEXT: sub r24, r18
|
|
; CHECK-NEXT: mov r25, r24
|
|
; CHECK-NEXT: lsl r25
|
|
; CHECK-NEXT: sbc r25, r25
|
|
; CHECK-NEXT: ret
|
|
;
|
|
; NOX-LABEL: foob3:
|
|
; NOX: ; %bb.0: ; %entry
|
|
; NOX-NEXT: subi r22, lo8(-(arrb5))
|
|
; NOX-NEXT: sbci r23, hi8(-(arrb5))
|
|
; NOX-NEXT: movw r30, r22
|
|
; NOX-NEXT: ldi r18, 4
|
|
; NOX-NEXT: out 59, r18
|
|
; NOX-NEXT: elpm
|
|
; NOX-NEXT: mov r18, r0
|
|
; NOX-NEXT: subi r24, lo8(-(arrb3))
|
|
; NOX-NEXT: sbci r25, hi8(-(arrb3))
|
|
; NOX-NEXT: movw r30, r24
|
|
; NOX-NEXT: ldi r24, 2
|
|
; NOX-NEXT: out 59, r24
|
|
; NOX-NEXT: elpm
|
|
; NOX-NEXT: mov r24, r0
|
|
; NOX-NEXT: sub r24, r18
|
|
; NOX-NEXT: mov r25, r24
|
|
; NOX-NEXT: lsl r25
|
|
; NOX-NEXT: sbc r25, r25
|
|
; NOX-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i8], [4 x i8] addrspace(3)* @arrb3, i16 0, i16 %a
|
|
%0 = load i8, i8 addrspace(3)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i8], [4 x i8] addrspace(5)* @arrb5, i16 0, i16 %b
|
|
%1 = load i8, i8 addrspace(5)* %arrayidx1, align 1
|
|
%sub = sub i8 %0, %1
|
|
ret i8 %sub
|
|
}
|
|
|
|
define signext i8 @foob4(i16 %a, i16 %b) {
|
|
; CHECK-LABEL: foob4:
|
|
; CHECK: ; %bb.0: ; %entry
|
|
; CHECK-NEXT: subi r22, lo8(-(arrb3))
|
|
; CHECK-NEXT: sbci r23, hi8(-(arrb3))
|
|
; CHECK-NEXT: movw r30, r22
|
|
; CHECK-NEXT: ldi r18, 2
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r19, Z
|
|
; CHECK-NEXT: subi r24, lo8(-(arrb3))
|
|
; CHECK-NEXT: sbci r25, hi8(-(arrb3))
|
|
; CHECK-NEXT: movw r30, r24
|
|
; CHECK-NEXT: out 59, r18
|
|
; CHECK-NEXT: elpm r24, Z
|
|
; CHECK-NEXT: sub r24, r19
|
|
; CHECK-NEXT: mov r25, r24
|
|
; CHECK-NEXT: lsl r25
|
|
; CHECK-NEXT: sbc r25, r25
|
|
; CHECK-NEXT: ret
|
|
;
|
|
; NOX-LABEL: foob4:
|
|
; NOX: ; %bb.0: ; %entry
|
|
; NOX-NEXT: subi r22, lo8(-(arrb3))
|
|
; NOX-NEXT: sbci r23, hi8(-(arrb3))
|
|
; NOX-NEXT: movw r30, r22
|
|
; NOX-NEXT: ldi r18, 2
|
|
; NOX-NEXT: out 59, r18
|
|
; NOX-NEXT: elpm
|
|
; NOX-NEXT: mov r19, r0
|
|
; NOX-NEXT: subi r24, lo8(-(arrb3))
|
|
; NOX-NEXT: sbci r25, hi8(-(arrb3))
|
|
; NOX-NEXT: movw r30, r24
|
|
; NOX-NEXT: out 59, r18
|
|
; NOX-NEXT: elpm
|
|
; NOX-NEXT: mov r24, r0
|
|
; NOX-NEXT: sub r24, r19
|
|
; NOX-NEXT: mov r25, r24
|
|
; NOX-NEXT: lsl r25
|
|
; NOX-NEXT: sbc r25, r25
|
|
; NOX-NEXT: ret
|
|
entry:
|
|
%arrayidx = getelementptr inbounds [4 x i8], [4 x i8] addrspace(3)* @arrb3, i16 0, i16 %a
|
|
%0 = load i8, i8 addrspace(3)* %arrayidx, align 1
|
|
%arrayidx1 = getelementptr inbounds [4 x i8], [4 x i8] addrspace(3)* @arrb3, i16 0, i16 %b
|
|
%1 = load i8, i8 addrspace(3)* %arrayidx1, align 1
|
|
%sub = sub i8 %0, %1
|
|
ret i8 %sub
|
|
}
|