| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=thumbv8m.main %s -o - | FileCheck %s --check-prefix=CHECK-V8M |
| ; RUN: llc -mtriple=armv8 %s -o - | FileCheck %s --check-prefix=CHECK-V8A |
| |
| define ptr @pre_inc_ldr(ptr %base, i32 %a) { |
| ; CHECK-V8M-LABEL: pre_inc_ldr: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldr r2, [r0, #4]! |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #4] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_inc_ldr: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldr r2, [r0, #4]! |
| ; CHECK-V8A-NEXT: add r1, r2, r1 |
| ; CHECK-V8A-NEXT: str r1, [r0, #4] |
| ; CHECK-V8A-NEXT: bx lr |
| %addr = getelementptr i32, ptr %base, i32 1 |
| %ld = load i32, ptr %addr |
| %addr.1 = getelementptr i32, ptr %base, i32 2 |
| %res = add i32 %ld, %a |
| store i32 %res, ptr %addr.1 |
| ret ptr %addr |
| } |
| |
| define ptr @pre_dec_ldr(ptr %base, i32 %a) { |
| ; CHECK-V8M-LABEL: pre_dec_ldr: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldr r2, [r0, #-4]! |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #12] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_dec_ldr: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldr r2, [r0, #-4]! |
| ; CHECK-V8A-NEXT: add r1, r2, r1 |
| ; CHECK-V8A-NEXT: str r1, [r0, #12] |
| ; CHECK-V8A-NEXT: bx lr |
| %addr = getelementptr i32, ptr %base, i32 -1 |
| %ld = load i32, ptr %addr |
| %addr.1 = getelementptr i32, ptr %base, i32 2 |
| %res = add i32 %ld, %a |
| store i32 %res, ptr %addr.1 |
| ret ptr %addr |
| } |
| |
| define ptr @post_inc_ldr(ptr %base, ptr %addr.2, i32 %a) { |
| ; CHECK-V8M-LABEL: post_inc_ldr: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldr r3, [r0], #4 |
| ; CHECK-V8M-NEXT: add r2, r3 |
| ; CHECK-V8M-NEXT: str r2, [r1] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: post_inc_ldr: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldr r3, [r0], #4 |
| ; CHECK-V8A-NEXT: add r2, r3, r2 |
| ; CHECK-V8A-NEXT: str r2, [r1] |
| ; CHECK-V8A-NEXT: bx lr |
| %ld = load i32, ptr %base |
| %addr.1 = getelementptr i32, ptr %base, i32 1 |
| %res = add i32 %ld, %a |
| store i32 %res, ptr %addr.2 |
| ret ptr %addr.1 |
| } |
| |
| define ptr @post_dec_ldr(ptr %base, ptr %addr.2, i32 %a) { |
| ; CHECK-V8M-LABEL: post_dec_ldr: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldr r3, [r0], #-4 |
| ; CHECK-V8M-NEXT: add r2, r3 |
| ; CHECK-V8M-NEXT: str r2, [r1] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: post_dec_ldr: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldr r3, [r0], #-4 |
| ; CHECK-V8A-NEXT: add r2, r3, r2 |
| ; CHECK-V8A-NEXT: str r2, [r1] |
| ; CHECK-V8A-NEXT: bx lr |
| %ld = load i32, ptr %base |
| %addr.1 = getelementptr i32, ptr %base, i32 -1 |
| %res = add i32 %ld, %a |
| store i32 %res, ptr %addr.2 |
| ret ptr %addr.1 |
| } |
| |
| define ptr @pre_inc_str(ptr %base, i32 %a, i32 %b) { |
| ; CHECK-V8M-LABEL: pre_inc_str: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #4]! |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_inc_str: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: add r1, r1, r2 |
| ; CHECK-V8A-NEXT: str r1, [r0, #4]! |
| ; CHECK-V8A-NEXT: bx lr |
| %addr.1 = getelementptr i32, ptr %base, i32 1 |
| %res = add i32 %a, %b |
| store i32 %res, ptr %addr.1 |
| ret ptr %addr.1 |
| } |
| |
| define ptr @pre_dec_str(ptr %base, i32 %a, i32 %b) { |
| ; CHECK-V8M-LABEL: pre_dec_str: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #-4]! |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_dec_str: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: add r1, r1, r2 |
| ; CHECK-V8A-NEXT: str r1, [r0, #-4]! |
| ; CHECK-V8A-NEXT: bx lr |
| %res = add i32 %a, %b |
| %addr.1 = getelementptr i32, ptr %base, i32 -1 |
| store i32 %res, ptr %addr.1 |
| ret ptr %addr.1 |
| } |
| |
| define ptr @post_inc_str(ptr %base, i32 %a, i32 %b) { |
| ; CHECK-V8M-LABEL: post_inc_str: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0], #4 |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: post_inc_str: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: add r1, r1, r2 |
| ; CHECK-V8A-NEXT: str r1, [r0], #4 |
| ; CHECK-V8A-NEXT: bx lr |
| %addr.1 = getelementptr i32, ptr %base, i32 1 |
| %res = add i32 %a, %b |
| store i32 %res, ptr %base |
| ret ptr %addr.1 |
| } |
| |
| define ptr @post_dec_str(ptr %base, i32 %a, i32 %b) { |
| ; CHECK-V8M-LABEL: post_dec_str: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0], #-4 |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: post_dec_str: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: add r1, r1, r2 |
| ; CHECK-V8A-NEXT: str r1, [r0], #-4 |
| ; CHECK-V8A-NEXT: bx lr |
| %addr.1 = getelementptr i32, ptr %base, i32 -1 |
| %res = add i32 %a, %b |
| store i32 %res, ptr %base |
| ret ptr %addr.1 |
| } |
| |
| ; TODO: Generate ldrd |
| define ptr @pre_inc_ldrd(ptr %base) { |
| ; CHECK-V8M-LABEL: pre_inc_ldrd: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldr r1, [r0, #4]! |
| ; CHECK-V8M-NEXT: ldr r2, [r0, #4] |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #8] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_inc_ldrd: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldr r1, [r0, #4]! |
| ; CHECK-V8A-NEXT: ldr r2, [r0, #4] |
| ; CHECK-V8A-NEXT: add r1, r1, r2 |
| ; CHECK-V8A-NEXT: str r1, [r0, #8] |
| ; CHECK-V8A-NEXT: bx lr |
| %addr = getelementptr i32, ptr %base, i32 1 |
| %addr.1 = getelementptr i32, ptr %base, i32 2 |
| %addr.2 = getelementptr i32, ptr %base, i32 3 |
| %ld = load i32, ptr %addr |
| %ld.1 = load i32, ptr %addr.1 |
| %res = add i32 %ld, %ld.1 |
| store i32 %res, ptr %addr.2 |
| ret ptr %addr |
| } |
| |
| ; TODO: Generate ldrd |
| define ptr @pre_dec_ldrd(ptr %base) { |
| ; CHECK-V8M-LABEL: pre_dec_ldrd: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldr r1, [r0, #-4]! |
| ; CHECK-V8M-NEXT: ldr r2, [r0, #-4] |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #-8] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_dec_ldrd: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldr r1, [r0, #-4]! |
| ; CHECK-V8A-NEXT: ldr r2, [r0, #-4] |
| ; CHECK-V8A-NEXT: add r1, r1, r2 |
| ; CHECK-V8A-NEXT: str r1, [r0, #-8] |
| ; CHECK-V8A-NEXT: bx lr |
| %addr = getelementptr i32, ptr %base, i32 -1 |
| %addr.1 = getelementptr i32, ptr %base, i32 -2 |
| %addr.2 = getelementptr i32, ptr %base, i32 -3 |
| %ld = load i32, ptr %addr |
| %ld.1 = load i32, ptr %addr.1 |
| %res = add i32 %ld, %ld.1 |
| store i32 %res, ptr %addr.2 |
| ret ptr %addr |
| } |
| |
| ; TODO: Generate post inc |
| define ptr @post_inc_ldrd(ptr %base, ptr %addr.3) { |
| ; CHECK-V8M-LABEL: post_inc_ldrd: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldrd r2, r3, [r0], #8 |
| ; CHECK-V8M-NEXT: add r2, r3 |
| ; CHECK-V8M-NEXT: str r2, [r1] |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: post_inc_ldrd: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldrd r2, r3, [r0] |
| ; CHECK-V8A-NEXT: add r0, r0, #8 |
| ; CHECK-V8A-NEXT: add r2, r2, r3 |
| ; CHECK-V8A-NEXT: str r2, [r1] |
| ; CHECK-V8A-NEXT: bx lr |
| %ld = load i32, ptr %base |
| %addr.1 = getelementptr i32, ptr %base, i32 1 |
| %ld.1 = load i32, ptr %addr.1 |
| %addr.2 = getelementptr i32, ptr %base, i32 2 |
| %res = add i32 %ld, %ld.1 |
| store i32 %res, ptr %addr.3 |
| ret ptr %addr.2 |
| } |
| |
| define ptr @pre_inc_str_multi(ptr %base) { |
| ; CHECK-V8M-LABEL: pre_inc_str_multi: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldrd r1, r2, [r0] |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #8]! |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_inc_str_multi: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldrd r2, r3, [r0] |
| ; CHECK-V8A-NEXT: add r1, r2, r3 |
| ; CHECK-V8A-NEXT: str r1, [r0, #8]! |
| ; CHECK-V8A-NEXT: bx lr |
| %addr.1 = getelementptr i32, ptr %base, i32 1 |
| %ld = load i32, ptr %base |
| %ld.1 = load i32, ptr %addr.1 |
| %res = add i32 %ld, %ld.1 |
| %addr.2 = getelementptr i32, ptr %base, i32 2 |
| store i32 %res, ptr %addr.2 |
| ret ptr %addr.2 |
| } |
| |
| define ptr @pre_dec_str_multi(ptr %base) { |
| ; CHECK-V8M-LABEL: pre_dec_str_multi: |
| ; CHECK-V8M: @ %bb.0: |
| ; CHECK-V8M-NEXT: ldrd r1, r2, [r0] |
| ; CHECK-V8M-NEXT: add r1, r2 |
| ; CHECK-V8M-NEXT: str r1, [r0, #-4]! |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: pre_dec_str_multi: |
| ; CHECK-V8A: @ %bb.0: |
| ; CHECK-V8A-NEXT: ldrd r2, r3, [r0] |
| ; CHECK-V8A-NEXT: add r1, r2, r3 |
| ; CHECK-V8A-NEXT: str r1, [r0, #-4]! |
| ; CHECK-V8A-NEXT: bx lr |
| %addr.1 = getelementptr i32, ptr %base, i32 1 |
| %ld = load i32, ptr %base |
| %ld.1 = load i32, ptr %addr.1 |
| %res = add i32 %ld, %ld.1 |
| %addr.2 = getelementptr i32, ptr %base, i32 -1 |
| store i32 %res, ptr %addr.2 |
| ret ptr %addr.2 |
| } |
| |
| define ptr @illegal_pre_inc_store_1(ptr %base) { |
| ; CHECK-V8M-LABEL: illegal_pre_inc_store_1: |
| ; CHECK-V8M: @ %bb.0: @ %entry |
| ; CHECK-V8M-NEXT: str r0, [r0, #8] |
| ; CHECK-V8M-NEXT: adds r0, #8 |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: illegal_pre_inc_store_1: |
| ; CHECK-V8A: @ %bb.0: @ %entry |
| ; CHECK-V8A-NEXT: str r0, [r0, #8] |
| ; CHECK-V8A-NEXT: add r0, r0, #8 |
| ; CHECK-V8A-NEXT: bx lr |
| entry: |
| %ptr.to.use = getelementptr i32, ptr %base, i32 2 |
| %ptr.to.store = ptrtoint ptr %base to i32 |
| store i32 %ptr.to.store, ptr %ptr.to.use, align 4 |
| ret ptr %ptr.to.use |
| } |
| |
| define ptr @legal_pre_inc_store_needs_copy_1(ptr %base) { |
| ; CHECK-V8M-LABEL: legal_pre_inc_store_needs_copy_1: |
| ; CHECK-V8M: @ %bb.0: @ %entry |
| ; CHECK-V8M-NEXT: add.w r1, r0, #8 |
| ; CHECK-V8M-NEXT: str r1, [r0, #8] |
| ; CHECK-V8M-NEXT: mov r0, r1 |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: legal_pre_inc_store_needs_copy_1: |
| ; CHECK-V8A: @ %bb.0: @ %entry |
| ; CHECK-V8A-NEXT: add r1, r0, #8 |
| ; CHECK-V8A-NEXT: str r1, [r0, #8] |
| ; CHECK-V8A-NEXT: mov r0, r1 |
| ; CHECK-V8A-NEXT: bx lr |
| entry: |
| %ptr.to.use = getelementptr i32, ptr %base, i32 2 |
| %ptr.to.store = ptrtoint ptr %ptr.to.use to i32 |
| store i32 %ptr.to.store, ptr %ptr.to.use, align 4 |
| ret ptr %ptr.to.use |
| } |
| |
| define ptr @legal_pre_inc_store_needs_copy_2(i32 %base) { |
| ; CHECK-V8M-LABEL: legal_pre_inc_store_needs_copy_2: |
| ; CHECK-V8M: @ %bb.0: @ %entry |
| ; CHECK-V8M-NEXT: str r0, [r0, #8] |
| ; CHECK-V8M-NEXT: adds r0, #8 |
| ; CHECK-V8M-NEXT: bx lr |
| ; |
| ; CHECK-V8A-LABEL: legal_pre_inc_store_needs_copy_2: |
| ; CHECK-V8A: @ %bb.0: @ %entry |
| ; CHECK-V8A-NEXT: str r0, [r0, #8] |
| ; CHECK-V8A-NEXT: add r0, r0, #8 |
| ; CHECK-V8A-NEXT: bx lr |
| entry: |
| %ptr = inttoptr i32 %base to ptr |
| %ptr.to.use = getelementptr i32, ptr %ptr, i32 2 |
| store i32 %base, ptr %ptr.to.use, align 4 |
| ret ptr %ptr.to.use |
| } |