mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
ecc0ff6b14
Other than PC-relative loads/store the patterns that match the various load/store addressing modes have the same complexity, so the order that they are matched is the order that they appear in the .td file. Rearrange the instruction definitions in ARMInstrThumb.td, and make use of AddedComplexity for PC-relative loads, so that the instruction matching order is the order that results in the simplest selection logic. This also makes register-offset load/store be selected when it should, as previously it was only selected for too-large immediate offsets. Differential Revision: http://reviews.llvm.org/D11800 llvm-svn: 244882
565 lines
14 KiB
LLVM
565 lines
14 KiB
LLVM
; RUN: llc -mtriple=thumbv6m-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-T1
|
|
; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-T2
|
|
|
|
|
|
; Register offset
|
|
|
|
; CHECK-LABEL: ldrsb_rr
|
|
; CHECK: ldrsb r0, [r0, r1]
|
|
define i32 @ldrsb_rr(i8* %p, i32 %n) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 %n
|
|
%0 = load i8, i8* %arrayidx, align 1
|
|
%conv = sext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrsh_rr
|
|
; CHECK-T1: lsls r1, r1, #1
|
|
; CHECK-T1: ldrsh r0, [r0, r1]
|
|
; CHECK-T2: ldrsh.w r0, [r0, r1, lsl #1]
|
|
define i32 @ldrsh_rr(i16* %p, i32 %n) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 %n
|
|
%0 = load i16, i16* %arrayidx, align 2
|
|
%conv = sext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrb_rr
|
|
; CHECK: ldrb r0, [r0, r1]
|
|
define i32 @ldrb_rr(i8* %p, i32 %n) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 %n
|
|
%0 = load i8, i8* %arrayidx, align 1
|
|
%conv = zext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrh_rr
|
|
; CHECK-T1: lsls r1, r1, #1
|
|
; CHECK-T1: ldrh r0, [r0, r1]
|
|
; CHECK-T2: ldrh.w r0, [r0, r1, lsl #1]
|
|
define i32 @ldrh_rr(i16* %p, i32 %n) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 %n
|
|
%0 = load i16, i16* %arrayidx, align 2
|
|
%conv = zext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldr_rr
|
|
; CHECK-T1: lsls r1, r1, #2
|
|
; CHECK-T1: ldr r0, [r0, r1]
|
|
; CHECK-T2: ldr.w r0, [r0, r1, lsl #2]
|
|
define i32 @ldr_rr(i32* %p, i32 %n) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i32, i32* %p, i32 %n
|
|
%0 = load i32, i32* %arrayidx, align 4
|
|
ret i32 %0
|
|
}
|
|
|
|
; CHECK-LABEL: strb_rr
|
|
; CHECK: strb r2, [r0, r1]
|
|
define void @strb_rr(i8* %p, i32 %n, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i8
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 %n
|
|
store i8 %conv, i8* %arrayidx, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: strh_rr
|
|
; CHECK-T1: lsls r1, r1, #1
|
|
; CHECK-T1: strh r2, [r0, r1]
|
|
; CHECK-T2: strh.w r2, [r0, r1, lsl #1]
|
|
define void @strh_rr(i16* %p, i32 %n, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i16
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 %n
|
|
store i16 %conv, i16* %arrayidx, align 2
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: str_rr
|
|
; CHECK-T1: lsls r1, r1, #2
|
|
; CHECK-T1: str r2, [r0, r1]
|
|
; CHECK-T2: str.w r2, [r0, r1, lsl #2]
|
|
define void @str_rr(i32* %p, i32 %n, i32 %x) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i32, i32* %p, i32 %n
|
|
store i32 %x, i32* %arrayidx, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
; Immediate offset of zero
|
|
|
|
; CHECK-LABEL: ldrsb_ri_zero
|
|
; CHECK-T1: ldrb r0, [r0]
|
|
; CHECK-T1: sxtb r0, r0
|
|
; CHECK-T2: ldrsb.w r0, [r0]
|
|
define i32 @ldrsb_ri_zero(i8* %p) {
|
|
entry:
|
|
%0 = load i8, i8* %p, align 1
|
|
%conv = sext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrsh_ri_zero
|
|
; CHECK-T1: ldrh r0, [r0]
|
|
; CHECK-T1: sxth r0, r0
|
|
; CHECK-T2: ldrsh.w r0, [r0]
|
|
define i32 @ldrsh_ri_zero(i16* %p) {
|
|
entry:
|
|
%0 = load i16, i16* %p, align 2
|
|
%conv = sext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrb_ri_zero
|
|
; CHECK: ldrb r0, [r0]
|
|
define i32 @ldrb_ri_zero(i8* %p) {
|
|
entry:
|
|
%0 = load i8, i8* %p, align 1
|
|
%conv = zext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrh_ri_zero
|
|
; CHECK: ldrh r0, [r0]
|
|
define i32 @ldrh_ri_zero(i16* %p) {
|
|
entry:
|
|
%0 = load i16, i16* %p, align 2
|
|
%conv = zext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldr_ri_zero
|
|
; CHECK: ldr r0, [r0]
|
|
define i32 @ldr_ri_zero(i32* %p) {
|
|
entry:
|
|
%0 = load i32, i32* %p, align 4
|
|
ret i32 %0
|
|
}
|
|
|
|
; CHECK-LABEL: strb_ri_zero
|
|
; CHECK: strb r1, [r0]
|
|
define void @strb_ri_zero(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i8
|
|
store i8 %conv, i8* %p, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: strh_ri_zero
|
|
; CHECK: strh r1, [r0]
|
|
define void @strh_ri_zero(i16* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i16
|
|
store i16 %conv, i16* %p, align 2
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: str_ri_zero
|
|
; CHECK: str r1, [r0]
|
|
define void @str_ri_zero(i32* %p, i32 %x) {
|
|
entry:
|
|
store i32 %x, i32* %p, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
; Maximum Thumb-1 immediate offset
|
|
|
|
; CHECK-LABEL: ldrsb_ri_t1_max
|
|
; CHECK-T1: movs r1, #31
|
|
; CHECK-T1: ldrsb r0, [r0, r1]
|
|
; CHECK-T2: ldrsb.w r0, [r0, #31]
|
|
define i32 @ldrsb_ri_t1_max(i8* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 31
|
|
%0 = load i8, i8* %arrayidx, align 1
|
|
%conv = sext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrsh_ri_t1_max
|
|
; CHECK-T1: movs r1, #62
|
|
; CHECK-T1: ldrsh r0, [r0, r1]
|
|
; CHECK-T2: ldrsh.w r0, [r0, #62]
|
|
define i32 @ldrsh_ri_t1_max(i16* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 31
|
|
%0 = load i16, i16* %arrayidx, align 2
|
|
%conv = sext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrb_ri_t1_max
|
|
; CHECK: ldrb r0, [r0, #31]
|
|
define i32 @ldrb_ri_t1_max(i8* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 31
|
|
%0 = load i8, i8* %arrayidx, align 1
|
|
%conv = zext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrh_ri_t1_max
|
|
; CHECK: ldrh r0, [r0, #62]
|
|
define i32 @ldrh_ri_t1_max(i16* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 31
|
|
%0 = load i16, i16* %arrayidx, align 2
|
|
%conv = zext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldr_ri_t1_max
|
|
; CHECK: ldr r0, [r0, #124]
|
|
define i32 @ldr_ri_t1_max(i32* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i32, i32* %p, i32 31
|
|
%0 = load i32, i32* %arrayidx, align 4
|
|
ret i32 %0
|
|
}
|
|
|
|
; CHECK-LABEL: strb_ri_t1_max
|
|
; CHECK: strb r1, [r0, #31]
|
|
define void @strb_ri_t1_max(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i8
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 31
|
|
store i8 %conv, i8* %arrayidx, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: strh_ri_t1_max
|
|
; CHECK: strh r1, [r0, #62]
|
|
define void @strh_ri_t1_max(i16* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i16
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 31
|
|
store i16 %conv, i16* %arrayidx, align 2
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: str_ri_t1_max
|
|
; CHECK: str r1, [r0, #124]
|
|
define void @str_ri_t1_max(i32* %p, i32 %x) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i32, i32* %p, i32 31
|
|
store i32 %x, i32* %arrayidx, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
; One past maximum Thumb-1 immediate offset
|
|
|
|
; CHECK-LABEL: ldrsb_ri_t1_too_big
|
|
; CHECK-T1: movs r1, #32
|
|
; CHECK-T1: ldrsb r0, [r0, r1]
|
|
; CHECK-T2: ldrsb.w r0, [r0, #32]
|
|
define i32 @ldrsb_ri_t1_too_big(i8* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 32
|
|
%0 = load i8, i8* %arrayidx, align 1
|
|
%conv = sext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrsh_ri_t1_too_big
|
|
; CHECK-T1: movs r1, #64
|
|
; CHECK-T1: ldrsh r0, [r0, r1]
|
|
; CHECK-T2: ldrsh.w r0, [r0, #64]
|
|
define i32 @ldrsh_ri_t1_too_big(i16* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 32
|
|
%0 = load i16, i16* %arrayidx, align 2
|
|
%conv = sext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrb_ri_t1_too_big
|
|
; CHECK-T1: movs r1, #32
|
|
; CHECK-T1: ldrb r0, [r0, r1]
|
|
; CHECK-T2: ldrb.w r0, [r0, #32]
|
|
define i32 @ldrb_ri_t1_too_big(i8* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 32
|
|
%0 = load i8, i8* %arrayidx, align 1
|
|
%conv = zext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrh_ri_t1_too_big
|
|
; CHECK-T1: movs r1, #64
|
|
; CHECK-T1: ldrh r0, [r0, r1]
|
|
; CHECK-T2: ldrh.w r0, [r0, #64]
|
|
define i32 @ldrh_ri_t1_too_big(i16* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 32
|
|
%0 = load i16, i16* %arrayidx, align 2
|
|
%conv = zext i16 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldr_ri_t1_too_big
|
|
; CHECK-T1: movs r1, #128
|
|
; CHECK-T1: ldr r0, [r0, r1]
|
|
; CHECK-T2: ldr.w r0, [r0, #128]
|
|
define i32 @ldr_ri_t1_too_big(i32* %p) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i32, i32* %p, i32 32
|
|
%0 = load i32, i32* %arrayidx, align 4
|
|
ret i32 %0
|
|
}
|
|
|
|
; CHECK-LABEL: strb_ri_t1_too_big
|
|
; CHECK-T1: movs r2, #32
|
|
; CHECK-T1: strb r1, [r0, r2]
|
|
; CHECK-T2: strb.w r1, [r0, #32]
|
|
define void @strb_ri_t1_too_big(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i8
|
|
%arrayidx = getelementptr inbounds i8, i8* %p, i32 32
|
|
store i8 %conv, i8* %arrayidx, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: strh_ri_t1_too_big
|
|
; CHECK-T1: movs r2, #64
|
|
; CHECK-T1: strh r1, [r0, r2]
|
|
; CHECK-T2: strh.w r1, [r0, #64]
|
|
define void @strh_ri_t1_too_big(i16* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i16
|
|
%arrayidx = getelementptr inbounds i16, i16* %p, i32 32
|
|
store i16 %conv, i16* %arrayidx, align 2
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: str_ri_t1_too_big
|
|
; CHECK-T1: movs r2, #128
|
|
; CHECK-T1: str r1, [r0, r2]
|
|
; CHECK-T2: str.w r1, [r0, #128]
|
|
define void @str_ri_t1_too_big(i32* %p, i32 %x) {
|
|
entry:
|
|
%arrayidx = getelementptr inbounds i32, i32* %p, i32 32
|
|
store i32 %x, i32* %arrayidx, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
; Maximum Thumb-2 immediate offset
|
|
|
|
; CHECK-LABEL: ldrsb_ri_t2_max
|
|
; CHECK-T1: ldr r1, .LCP
|
|
; CHECK-T1: ldrsb r0, [r0, r1]
|
|
; CHECK-T2: ldrsb.w r0, [r0, #4095]
|
|
define i32 @ldrsb_ri_t2_max(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = load i8, i8* %add.ptr, align 1
|
|
%conv = sext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrsh_ri_t2_max
|
|
; CHECK-T1: ldr r1, .LCP
|
|
; CHECK-T1: ldrsh r0, [r0, r1]
|
|
; CHECK-T2: ldrsh.w r0, [r0, #4095]
|
|
define i32 @ldrsh_ri_t2_max(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = bitcast i8* %add.ptr to i16*
|
|
%1 = load i16, i16* %0, align 2
|
|
%conv = sext i16 %1 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrb_ri_t2_max
|
|
; CHECK-T1: ldr r1, .LCP
|
|
; CHECK-T1: ldrb r0, [r0, r1]
|
|
; CHECK-T2: ldrb.w r0, [r0, #4095]
|
|
define i32 @ldrb_ri_t2_max(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = load i8, i8* %add.ptr, align 1
|
|
%conv = zext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrh_ri_t2_max
|
|
; CHECK-T1: ldr r1, .LCP
|
|
; CHECK-T1: ldrh r0, [r0, r1]
|
|
; CHECK-T2: ldrh.w r0, [r0, #4095]
|
|
define i32 @ldrh_ri_t2_max(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = bitcast i8* %add.ptr to i16*
|
|
%1 = load i16, i16* %0, align 2
|
|
%conv = zext i16 %1 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldr_ri_t2_max
|
|
; CHECK-T1: ldr r1, .LCP
|
|
; CHECK-T1: ldr r0, [r0, r1]
|
|
; CHECK-T2: ldr.w r0, [r0, #4095]
|
|
define i32 @ldr_ri_t2_max(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = bitcast i8* %add.ptr to i32*
|
|
%1 = load i32, i32* %0, align 4
|
|
ret i32 %1
|
|
}
|
|
|
|
; CHECK-LABEL: strb_ri_t2_max
|
|
; CHECK-T1: ldr r2, .LCP
|
|
; CHECK-T1: strb r1, [r0, r2]
|
|
; CHECK-T2: strb.w r1, [r0, #4095]
|
|
define void @strb_ri_t2_max(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i8
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
store i8 %conv, i8* %add.ptr, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: strh_ri_t2_max
|
|
; CHECK-T1: ldr r2, .LCP
|
|
; CHECK-T1: strh r1, [r0, r2]
|
|
; CHECK-T2: strh.w r1, [r0, #4095]
|
|
define void @strh_ri_t2_max(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i16
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = bitcast i8* %add.ptr to i16*
|
|
store i16 %conv, i16* %0, align 2
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: str_ri_t2_max
|
|
; CHECK-T1: ldr r2, .LCP
|
|
; CHECK-T1: str r1, [r0, r2]
|
|
; CHECK-T2: str.w r1, [r0, #4095]
|
|
define void @str_ri_t2_max(i8* %p, i32 %x) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
|
|
%0 = bitcast i8* %add.ptr to i32*
|
|
store i32 %x, i32* %0, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
; One past maximum Thumb-2 immediate offset
|
|
|
|
; CHECK-LABEL: ldrsb_ri_t2_too_big
|
|
; CHECK-T1: movs r1, #1
|
|
; CHECK-T1: lsls r1, r1, #12
|
|
; CHECK-T2: mov.w r1, #4096
|
|
; CHECK: ldrsb r0, [r0, r1]
|
|
define i32 @ldrsb_ri_t2_too_big(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = load i8, i8* %add.ptr, align 1
|
|
%conv = sext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrsh_ri_t2_too_big
|
|
; CHECK-T1: movs r1, #1
|
|
; CHECK-T1: lsls r1, r1, #12
|
|
; CHECK-T2: mov.w r1, #4096
|
|
; CHECK: ldrsh r0, [r0, r1]
|
|
define i32 @ldrsh_ri_t2_too_big(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = bitcast i8* %add.ptr to i16*
|
|
%1 = load i16, i16* %0, align 2
|
|
%conv = sext i16 %1 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrb_ri_t2_too_big
|
|
; CHECK-T1: movs r1, #1
|
|
; CHECK-T1: lsls r1, r1, #12
|
|
; CHECK-T2: mov.w r1, #4096
|
|
; CHECK: ldrb r0, [r0, r1]
|
|
define i32 @ldrb_ri_t2_too_big(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = load i8, i8* %add.ptr, align 1
|
|
%conv = zext i8 %0 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldrh_ri_t2_too_big
|
|
; CHECK-T1: movs r1, #1
|
|
; CHECK-T1: lsls r1, r1, #12
|
|
; CHECK-T2: mov.w r1, #4096
|
|
; CHECK: ldrh r0, [r0, r1]
|
|
define i32 @ldrh_ri_t2_too_big(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = bitcast i8* %add.ptr to i16*
|
|
%1 = load i16, i16* %0, align 2
|
|
%conv = zext i16 %1 to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; CHECK-LABEL: ldr_ri_t2_too_big
|
|
; CHECK-T1: movs r1, #1
|
|
; CHECK-T1: lsls r1, r1, #12
|
|
; CHECK-T2: mov.w r1, #4096
|
|
; CHECK: ldr r0, [r0, r1]
|
|
define i32 @ldr_ri_t2_too_big(i8* %p) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = bitcast i8* %add.ptr to i32*
|
|
%1 = load i32, i32* %0, align 4
|
|
ret i32 %1
|
|
}
|
|
|
|
; CHECK-LABEL: strb_ri_t2_too_big
|
|
; CHECK-T1: movs r2, #1
|
|
; CHECK-T1: lsls r2, r2, #12
|
|
; CHECK-T2: mov.w r2, #4096
|
|
; CHECK: strb r1, [r0, r2]
|
|
define void @strb_ri_t2_too_big(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i8
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
store i8 %conv, i8* %add.ptr, align 1
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: strh_ri_t2_too_big
|
|
; CHECK-T1: movs r2, #1
|
|
; CHECK-T1: lsls r2, r2, #12
|
|
; CHECK-T2: mov.w r2, #4096
|
|
; CHECK: strh r1, [r0, r2]
|
|
define void @strh_ri_t2_too_big(i8* %p, i32 %x) {
|
|
entry:
|
|
%conv = trunc i32 %x to i16
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = bitcast i8* %add.ptr to i16*
|
|
store i16 %conv, i16* %0, align 2
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: str_ri_t2_too_big
|
|
; CHECK-T1: movs r2, #1
|
|
; CHECK-T1: lsls r2, r2, #12
|
|
; CHECK-T2: mov.w r2, #4096
|
|
; CHECK: str r1, [r0, r2]
|
|
define void @str_ri_t2_too_big(i8* %p, i32 %x) {
|
|
entry:
|
|
%add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
|
|
%0 = bitcast i8* %add.ptr to i32*
|
|
store i32 %x, i32* %0, align 4
|
|
ret void
|
|
}
|