blob: 0d39dff94c87076c371594460a672b5419d10e60 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu \
; RUN: -mattr=+spe -O2 | FileCheck %s
; Regression test for a bug where evldd and evstdd used an offset that does not actually fit
; in the instruction encoding. They have a 5-bit displacement that gets multiplied by 8, so
; the maximum offset they can encode is `31 * 8 = 248`. For anything higher, these instructions
; cannot be used.
declare void @use(ptr)
define void @store_in_range(double %x) {
; CHECK-LABEL: store_in_range:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -256(1)
; CHECK-NEXT: stw 0, 260(1)
; CHECK-NEXT: .cfi_def_cfa_offset 256
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: evmergelo 3, 3, 4
; CHECK-NEXT: evstdd 3, 248(1)
; CHECK-NEXT: addi 3, 1, 8
; CHECK-NEXT: bl use
; CHECK-NEXT: lwz 0, 260(1)
; CHECK-NEXT: addi 1, 1, 256
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%d = alloca double, align 8
%large = alloca [240 x i8], align 8
store double %x, ptr %d, align 8
call void @use(ptr %large)
ret void
}
define void @store_unaligned_in_range(double %x) {
; CHECK-LABEL: store_unaligned_in_range:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -32(1)
; CHECK-NEXT: stw 0, 36(1)
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: evmergelo 3, 3, 4
; CHECK-NEXT: evstdd 3, 8(1)
; CHECK-NEXT: lwz 3, 8(1)
; CHECK-NEXT: stw 3, 17(1)
; CHECK-NEXT: lwz 3, 12(1)
; CHECK-NEXT: stw 3, 21(1)
; CHECK-NEXT: addi 3, 1, 16
; CHECK-NEXT: bl use
; CHECK-NEXT: lwz 0, 36(1)
; CHECK-NEXT: addi 1, 1, 32
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%buf = alloca [16 x i8], align 8
%p = getelementptr i8, ptr %buf, i32 1
store double %x, ptr %p, align 1
call void @use(ptr %buf)
ret void
}
define void @store_unaligned_offset_248(double %x) {
; CHECK-LABEL: store_unaligned_offset_248:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -288(1)
; CHECK-NEXT: stw 0, 292(1)
; CHECK-NEXT: .cfi_def_cfa_offset 288
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: evmergelo 3, 3, 4
; CHECK-NEXT: evstdd 3, 16(1)
; CHECK-NEXT: lwz 3, 16(1)
; CHECK-NEXT: stw 3, 273(1)
; CHECK-NEXT: lwz 3, 20(1)
; CHECK-NEXT: stw 3, 277(1)
; CHECK-NEXT: addi 3, 1, 24
; CHECK-NEXT: bl use
; CHECK-NEXT: lwz 0, 292(1)
; CHECK-NEXT: addi 1, 1, 288
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%buf = alloca [264 x i8], align 8
%p = getelementptr i8, ptr %buf, i32 249
store double %x, ptr %p, align 1
call void @use(ptr %buf)
ret void
}
define void @store_out_of_range(double %x) {
; CHECK-LABEL: store_out_of_range:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -272(1)
; CHECK-NEXT: stw 0, 276(1)
; CHECK-NEXT: .cfi_def_cfa_offset 272
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: evmergelo 3, 3, 4
; CHECK-NEXT: li 4, 264
; CHECK-NEXT: evstddx 3, 1, 4
; CHECK-NEXT: addi 3, 1, 16
; CHECK-NEXT: bl use
; CHECK-NEXT: lwz 0, 276(1)
; CHECK-NEXT: addi 1, 1, 272
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%d = alloca double, align 8
%large = alloca [248 x i8], align 8
store double %x, ptr %d, align 8
call void @use(ptr %large)
ret void
}
define double @load_in_range() {
; CHECK-LABEL: load_in_range:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -256(1)
; CHECK-NEXT: stw 0, 260(1)
; CHECK-NEXT: .cfi_def_cfa_offset 256
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: addi 3, 1, 248
; CHECK-NEXT: bl use
; CHECK-NEXT: addi 3, 1, 8
; CHECK-NEXT: bl use
; CHECK-NEXT: evldd 4, 248(1)
; CHECK-NEXT: evmergehi 3, 4, 4
; CHECK-NEXT: lwz 0, 260(1)
; CHECK-NEXT: addi 1, 1, 256
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%d = alloca double, align 8
%large = alloca [240 x i8], align 8
call void @use(ptr %d)
call void @use(ptr %large)
%v = load double, ptr %d, align 8
ret double %v
}
define double @load_unaligned_in_range() {
; CHECK-LABEL: load_unaligned_in_range:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -32(1)
; CHECK-NEXT: stw 0, 36(1)
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: addi 3, 1, 16
; CHECK-NEXT: bl use
; CHECK-NEXT: lwz 3, 17(1)
; CHECK-NEXT: stw 3, 8(1)
; CHECK-NEXT: lwz 3, 21(1)
; CHECK-NEXT: stw 3, 12(1)
; CHECK-NEXT: evldd 4, 8(1)
; CHECK-NEXT: evmergehi 3, 4, 4
; CHECK-NEXT: lwz 0, 36(1)
; CHECK-NEXT: addi 1, 1, 32
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%buf = alloca [16 x i8], align 8
%p = getelementptr i8, ptr %buf, i32 1
call void @use(ptr %buf)
%v = load double, ptr %p, align 1
ret double %v
}
define double @load_unaligned_offset_248() {
; CHECK-LABEL: load_unaligned_offset_248:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -272(1)
; CHECK-NEXT: stw 0, 276(1)
; CHECK-NEXT: .cfi_def_cfa_offset 272
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: addi 3, 1, 16
; CHECK-NEXT: bl use
; CHECK-NEXT: lwz 3, 265(1)
; CHECK-NEXT: stw 3, 8(1)
; CHECK-NEXT: lwz 3, 269(1)
; CHECK-NEXT: stw 3, 12(1)
; CHECK-NEXT: evldd 4, 8(1)
; CHECK-NEXT: evmergehi 3, 4, 4
; CHECK-NEXT: lwz 0, 276(1)
; CHECK-NEXT: addi 1, 1, 272
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%buf = alloca [256 x i8], align 8
%p = getelementptr i8, ptr %buf, i32 249
call void @use(ptr %buf)
%v = load double, ptr %p, align 1
ret double %v
}
define double @load_out_of_range() {
; CHECK-LABEL: load_out_of_range:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
; CHECK-NEXT: stwu 1, -272(1)
; CHECK-NEXT: stw 0, 276(1)
; CHECK-NEXT: .cfi_def_cfa_offset 272
; CHECK-NEXT: .cfi_offset lr, 4
; CHECK-NEXT: addi 3, 1, 264
; CHECK-NEXT: bl use
; CHECK-NEXT: addi 3, 1, 16
; CHECK-NEXT: bl use
; CHECK-NEXT: li 3, 264
; CHECK-NEXT: evlddx 4, 1, 3
; CHECK-NEXT: evmergehi 3, 4, 4
; CHECK-NEXT: lwz 0, 276(1)
; CHECK-NEXT: addi 1, 1, 272
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%d = alloca double, align 8
%large = alloca [248 x i8], align 8
call void @use(ptr %d)
call void @use(ptr %large)
%v = load double, ptr %d, align 8
ret double %v
}