Compiler projects using llvm
; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=-vsx -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck %s --check-prefix=ELF64
; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=+vsx -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck %s --check-prefix=VSX
; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=spe  -mtriple=powerpc-unknown-linux-gnu -mcpu=e500 | FileCheck %s --check-prefix=SPE

; This test verifies that load/store instructions are properly generated,
; and that they pass MI verification.

@a = dso_local global i8 1, align 1
@b = dso_local global i16 2, align 2
@c = dso_local global i32 4, align 4
@d = dso_local global i64 8, align 8
@e = dso_local global float 1.25, align 4
@f = dso_local global double 3.5, align 8

%struct.s = type<{ i8, i32 }>
%struct.t = type<{ i8, i64 }>

@g = dso_local global %struct.s <{ i8 1, i32 2 }>, align 1
@h = dso_local global %struct.t <{ i8 1, i64 2 }>, align 1

@i = common dso_local global [8192 x i64] zeroinitializer, align 8

; load

define i8 @t1() nounwind {
; ELF64-LABEL: t1:
  %1 = load i8, i8* @a, align 1
; ELF64: lbz
  %2 = add nsw i8 %1, 1
; ELF64: addi
  ret i8 %2
}

define i16 @t2() nounwind {
; ELF64-LABEL: t2:
  %1 = load i16, i16* @b, align 2
; ELF64: lhz
  %2 = add nsw i16 %1, 1
; ELF64: addi
  ret i16 %2
}

define dso_local i32 @t3() nounwind {
; ELF64-LABEL: t3:
  %1 = load i32, i32* @c, align 4
; ELF64: lwz
  %2 = add nsw i32 %1, 1
; ELF64: addi
  ret i32 %2
}

define i64 @t4() nounwind {
; ELF64-LABEL: t4:
  %1 = load i64, i64* @d, align 4
; ELF64: ld
  %2 = add nsw i64 %1, 1
; ELF64: addi
  ret i64 %2
}

define dso_local float @t5() nounwind {
; ELF64-LABEL: t5:
; SPE-LABEL: t5:
  %1 = load float, float* @e, align 4
; ELF64: lfs
; SPE: lwz
  %2 = fadd float %1, 1.0
; ELF64: fadds
; SPE: efsadd
  ret float %2
}

define dso_local double @t6() nounwind {
; ELF64-LABEL: t6:
; SPE-LABEL: t6:
  %1 = load double, double* @f, align 8
; ELF64: lfd
; VSX: lxsdx
; SPE: evldd
  %2 = fadd double %1, 1.0
; ELF64: fadd
; VSX: xsadddp
; SPE: efdadd
  ret double %2
}

; store

define dso_local void @t7(i8 %v) nounwind {
; ELF64-LABEL: t7:
  %1 = add nsw i8 %v, 1
  store i8 %1, i8* @a, align 1
; ELF64: addi
; ELF64: addis
; ELF64: addi
; ELF64: stb
  ret void
}

define dso_local void @t8(i16 %v) nounwind {
; ELF64-LABEL: t8:
  %1 = add nsw i16 %v, 1
  store i16 %1, i16* @b, align 2
; ELF64: addi
; ELF64: addis
; ELF64: addi
; ELF64: sth
  ret void
}

define dso_local void @t9(i32 %v) nounwind {
; ELF64-LABEL: t9:
  %1 = add nsw i32 %v, 1
  store i32 %1, i32* @c, align 4
; ELF64: addi
; ELF64: addis
; ELF64: addi
; ELF64: stw
  ret void
}

define dso_local void @t10(i64 %v) nounwind {
; ELF64-LABEL: t10:
  %1 = add nsw i64 %v, 1
  store i64 %1, i64* @d, align 4
; ELF64: addi
; ELF64: addis
; ELF64: addi
; ELF64: std
  ret void
}

define dso_local void @t11(float %v) nounwind {
; ELF64-LABEL: t11:
; SPE-LABEL: t11:
  %1 = fadd float %v, 1.0
  store float %1, float* @e, align 4
; ELF64: fadds
; ELF64: stfs
; SPE: efsadd
; SPE: stw
  ret void
}

define dso_local void @t12(double %v) nounwind {
; ELF64-LABEL: t12:
; SPE-LABEL: t12:
  %1 = fadd double %v, 1.0
  store double %1, double* @f, align 8
; ELF64: fadd
; ELF64: stfd
; VSX: xsadddp
; VSX: stxsdx
; SPE: efdadd
; SPE: evstdd
  ret void
}

;; lwa requires an offset divisible by 4, so we need lwax here.
define i64 @t13() nounwind {
; ELF64-LABEL: t13:
  %1 = load i32, i32* getelementptr inbounds (%struct.s, %struct.s* @g, i32 0, i32 1), align 1
  %2 = sext i32 %1 to i64
; ELF64: li
; ELF64: lwax
  %3 = add nsw i64 %2, 1
; ELF64: addi
  ret i64 %3
}

;; ld requires an offset divisible by 4, so we need ldx here.
define i64 @t14() nounwind {
; ELF64-LABEL: t14:
  %1 = load i64, i64* getelementptr inbounds (%struct.t, %struct.t* @h, i32 0, i32 1), align 1
; ELF64: li
; ELF64: ldx
  %2 = add nsw i64 %1, 1
; ELF64: addi
  ret i64 %2
}

;; std requires an offset divisible by 4, so we need stdx here.
define dso_local void @t15(i64 %v) nounwind {
; ELF64-LABEL: t15:
  %1 = add nsw i64 %v, 1
  store i64 %1, i64* getelementptr inbounds (%struct.t, %struct.t* @h, i32 0, i32 1), align 1
; ELF64: addi
; ELF64: addis
; ELF64: addi
; ELF64: li
; ELF64: stdx
  ret void
}

;; ld requires an offset that fits in 16 bits, so we need ldx here.
define i64 @t16() nounwind {
; ELF64-LABEL: t16:
  %1 = load i64, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8
; ELF64: lis
; ELF64: ori
; ELF64: ldx
  %2 = add nsw i64 %1, 1
; ELF64: addi
  ret i64 %2
}

;; std requires an offset that fits in 16 bits, so we need stdx here.
define dso_local void @t17(i64 %v) nounwind {
; ELF64-LABEL: t17:
  %1 = add nsw i64 %v, 1
  store i64 %1, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8
; ELF64: addi
; ELF64: addis
; ELF64: addi
; ELF64: lis
; ELF64: ori
; ELF64: stdx
  ret void
}