llvm/llvm/test/CodeGen/PowerPC/P10-stack-alignment.ll

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
; RUN:   -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
; RUN:   FileCheck %s --check-prefix=CHECK-LE
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN:   -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
; RUN:   FileCheck %s --check-prefix=CHECK-BE
; RUN: opt --passes='sroa,loop-vectorize,loop-unroll,instcombine' -S \
; RUN: -vectorizer-maximize-bandwidth --mtriple=powerpc64le-- -mcpu=pwr10 < %s | \
; RUN: FileCheck %s --check-prefix=CHECK-OPT

target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"

define dso_local signext i32 @test_32byte_vector() nounwind {
; CHECK-LE-LABEL: test_32byte_vector:
; CHECK-LE:       # %bb.0: # %entry
; CHECK-LE-NEXT:    mflr r0
; CHECK-LE-NEXT:    std r30, -16(r1)
; CHECK-LE-NEXT:    mr r30, r1
; CHECK-LE-NEXT:    std r0, 16(r1)
; CHECK-LE-NEXT:    clrldi r0, r1, 59
; CHECK-LE-NEXT:    subfic r0, r0, -96
; CHECK-LE-NEXT:    stdux r1, r1, r0
; CHECK-LE-NEXT:    addis r3, r2, .LCPI0_0@toc@ha
; CHECK-LE-NEXT:    addi r3, r3, .LCPI0_0@toc@l
; CHECK-LE-NEXT:    lxvd2x vs0, 0, r3
; CHECK-LE-NEXT:    addi r3, r1, 48
; CHECK-LE-NEXT:    stxvd2x vs0, 0, r3
; CHECK-LE-NEXT:    addis r3, r2, .LCPI0_1@toc@ha
; CHECK-LE-NEXT:    addi r3, r3, .LCPI0_1@toc@l
; CHECK-LE-NEXT:    lxvd2x vs0, 0, r3
; CHECK-LE-NEXT:    addi r3, r1, 32
; CHECK-LE-NEXT:    stxvd2x vs0, 0, r3
; CHECK-LE-NEXT:    bl test
; CHECK-LE-NEXT:    nop
; CHECK-LE-NEXT:    lwa r3, 32(r1)
; CHECK-LE-NEXT:    mr r1, r30
; CHECK-LE-NEXT:    ld r0, 16(r1)
; CHECK-LE-NEXT:    ld r30, -16(r1)
; CHECK-LE-NEXT:    mtlr r0
; CHECK-LE-NEXT:    blr
;
; CHECK-BE-LABEL: test_32byte_vector:
; CHECK-BE:       # %bb.0: # %entry
; CHECK-BE-NEXT:    mflr r0
; CHECK-BE-NEXT:    std r30, -16(r1)
; CHECK-BE-NEXT:    std r0, 16(r1)
; CHECK-BE-NEXT:    clrldi r0, r1, 59
; CHECK-BE-NEXT:    mr r30, r1
; CHECK-BE-NEXT:    subfic r0, r0, -192
; CHECK-BE-NEXT:    stdux r1, r1, r0
; CHECK-BE-NEXT:    lis r3, -8192
; CHECK-BE-NEXT:    li r4, 5
; CHECK-BE-NEXT:    lis r5, -16384
; CHECK-BE-NEXT:    lis r6, -32768
; CHECK-BE-NEXT:    ori r3, r3, 1
; CHECK-BE-NEXT:    rldic r4, r4, 32, 29
; CHECK-BE-NEXT:    ori r5, r5, 1
; CHECK-BE-NEXT:    ori r6, r6, 1
; CHECK-BE-NEXT:    rldic r3, r3, 3, 29
; CHECK-BE-NEXT:    ori r4, r4, 6
; CHECK-BE-NEXT:    rldic r5, r5, 2, 30
; CHECK-BE-NEXT:    rldic r6, r6, 1, 31
; CHECK-BE-NEXT:    std r3, 152(r1)
; CHECK-BE-NEXT:    addi r3, r1, 128
; CHECK-BE-NEXT:    std r4, 144(r1)
; CHECK-BE-NEXT:    std r5, 136(r1)
; CHECK-BE-NEXT:    std r6, 128(r1)
; CHECK-BE-NEXT:    bl test
; CHECK-BE-NEXT:    nop
; CHECK-BE-NEXT:    lwa r3, 128(r1)
; CHECK-BE-NEXT:    mr r1, r30
; CHECK-BE-NEXT:    ld r0, 16(r1)
; CHECK-BE-NEXT:    ld r30, -16(r1)
; CHECK-BE-NEXT:    mtlr r0
; CHECK-BE-NEXT:    blr
entry:
  %a = alloca <8 x i32>, align 32
  call void @llvm.lifetime.start.p0(i64 32, ptr %a)
  store <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>, ptr %a, align 32
  call void @test(ptr %a)
  %0 = load <8 x i32>, ptr %a, align 32
  %vecext = extractelement <8 x i32> %0, i32 0
  call void @llvm.lifetime.end.p0(i64 32, ptr %a)
  ret i32 %vecext
}

define dso_local signext i32 @test_32byte_aligned_vector() nounwind {
; CHECK-LE-LABEL: test_32byte_aligned_vector:
; CHECK-LE:       # %bb.0: # %entry
; CHECK-LE-NEXT:    mflr r0
; CHECK-LE-NEXT:    std r30, -16(r1)
; CHECK-LE-NEXT:    mr r30, r1
; CHECK-LE-NEXT:    std r0, 16(r1)
; CHECK-LE-NEXT:    clrldi r0, r1, 59
; CHECK-LE-NEXT:    subfic r0, r0, -64
; CHECK-LE-NEXT:    stdux r1, r1, r0
; CHECK-LE-NEXT:    addis r3, r2, .LCPI1_0@toc@ha
; CHECK-LE-NEXT:    addi r3, r3, .LCPI1_0@toc@l
; CHECK-LE-NEXT:    lxvd2x vs0, 0, r3
; CHECK-LE-NEXT:    addi r3, r1, 32
; CHECK-LE-NEXT:    stxvd2x vs0, 0, r3
; CHECK-LE-NEXT:    bl test1
; CHECK-LE-NEXT:    nop
; CHECK-LE-NEXT:    lwa r3, 32(r1)
; CHECK-LE-NEXT:    mr r1, r30
; CHECK-LE-NEXT:    ld r0, 16(r1)
; CHECK-LE-NEXT:    ld r30, -16(r1)
; CHECK-LE-NEXT:    mtlr r0
; CHECK-LE-NEXT:    blr
;
; CHECK-BE-LABEL: test_32byte_aligned_vector:
; CHECK-BE:       # %bb.0: # %entry
; CHECK-BE-NEXT:    mflr r0
; CHECK-BE-NEXT:    std r30, -16(r1)
; CHECK-BE-NEXT:    std r0, 16(r1)
; CHECK-BE-NEXT:    clrldi r0, r1, 59
; CHECK-BE-NEXT:    mr r30, r1
; CHECK-BE-NEXT:    subfic r0, r0, -160
; CHECK-BE-NEXT:    stdux r1, r1, r0
; CHECK-BE-NEXT:    lis r3, -16384
; CHECK-BE-NEXT:    lis r4, -32768
; CHECK-BE-NEXT:    ori r3, r3, 1
; CHECK-BE-NEXT:    ori r4, r4, 1
; CHECK-BE-NEXT:    rldic r3, r3, 2, 30
; CHECK-BE-NEXT:    rldic r4, r4, 1, 31
; CHECK-BE-NEXT:    std r3, 136(r1)
; CHECK-BE-NEXT:    addi r3, r1, 128
; CHECK-BE-NEXT:    std r4, 128(r1)
; CHECK-BE-NEXT:    bl test1
; CHECK-BE-NEXT:    nop
; CHECK-BE-NEXT:    lwa r3, 128(r1)
; CHECK-BE-NEXT:    mr r1, r30
; CHECK-BE-NEXT:    ld r0, 16(r1)
; CHECK-BE-NEXT:    ld r30, -16(r1)
; CHECK-BE-NEXT:    mtlr r0
; CHECK-BE-NEXT:    blr
entry:
  %a = alloca <4 x i32>, align 32
  call void @llvm.lifetime.start.p0(i64 16, ptr %a)
  store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %a, align 32
  call void @test1(ptr %a)
  %0 = load <4 x i32>, ptr %a, align 32
  %vecext = extractelement <4 x i32> %0, i32 0
  call void @llvm.lifetime.end.p0(i64 16, ptr %a)
  ret i32 %vecext
}


@Arr1 = dso_local global [64 x i8] zeroinitializer, align 1

define dso_local void @test_Array() nounwind {
; CHECK-OPT-LABEL: @test_Array(
; CHECK-OPT-NEXT: entry:
; CHECK-OPT-NEXT: %Arr2 = alloca [64 x i16], align 2
; CHECK-OPT: store <16 x i16> [[TMP0:%.*]], ptr [[TMP0:%.*]], align 2
; CHECK-LE-LABEL: test_Array:
; CHECK-LE:       # %bb.0: # %entry
; CHECK-LE-NEXT:    mflr r0
; CHECK-LE-NEXT:    stdu r1, -176(r1)
; CHECK-LE-NEXT:    li r3, 0
; CHECK-LE-NEXT:    addis r4, r2, Arr1@toc@ha
; CHECK-LE-NEXT:    li r6, 65
; CHECK-LE-NEXT:    std r0, 192(r1)
; CHECK-LE-NEXT:    addi r5, r1, 46
; CHECK-LE-NEXT:    stw r3, 44(r1)
; CHECK-LE-NEXT:    addi r4, r4, Arr1@toc@l
; CHECK-LE-NEXT:    mtctr r6
; CHECK-LE-NEXT:    addi r4, r4, -1
; CHECK-LE-NEXT:    bdz .LBB2_2
; CHECK-LE-NEXT:    .p2align 5
; CHECK-LE-NEXT:  .LBB2_1: # %for.body
; CHECK-LE-NEXT:    #
; CHECK-LE-NEXT:    lbz r6, 1(r4)
; CHECK-LE-NEXT:    addi r4, r4, 1
; CHECK-LE-NEXT:    addi r3, r3, 1
; CHECK-LE-NEXT:    sth r6, 2(r5)
; CHECK-LE-NEXT:    addi r5, r5, 2
; CHECK-LE-NEXT:    bdnz .LBB2_1
; CHECK-LE-NEXT:  .LBB2_2: # %for.cond.cleanup
; CHECK-LE-NEXT:    addi r3, r1, 48
; CHECK-LE-NEXT:    bl test_arr
; CHECK-LE-NEXT:    nop
; CHECK-LE-NEXT:    addi r1, r1, 176
; CHECK-LE-NEXT:    ld r0, 16(r1)
; CHECK-LE-NEXT:    mtlr r0
; CHECK-LE-NEXT:    blr
;
; CHECK-BE-LABEL: test_Array:
; CHECK-BE:       # %bb.0: # %entry
; CHECK-BE-NEXT:    mflr r0
; CHECK-BE-NEXT:    stdu r1, -256(r1)
; CHECK-BE-NEXT:    addis r5, r2, Arr1@toc@ha
; CHECK-BE-NEXT:    li r3, 0
; CHECK-BE-NEXT:    addi r5, r5, Arr1@toc@l
; CHECK-BE-NEXT:    std r0, 272(r1)
; CHECK-BE-NEXT:    addi r4, r1, 126
; CHECK-BE-NEXT:    li r6, 65
; CHECK-BE-NEXT:    stw r3, 124(r1)
; CHECK-BE-NEXT:    addi r5, r5, -1
; CHECK-BE-NEXT:    mtctr r6
; CHECK-BE-NEXT:    bdz .LBB2_2
; CHECK-BE-NEXT:  .LBB2_1: # %for.body
; CHECK-BE-NEXT:    #
; CHECK-BE-NEXT:    lbz r6, 1(r5)
; CHECK-BE-NEXT:    addi r5, r5, 1
; CHECK-BE-NEXT:    addi r3, r3, 1
; CHECK-BE-NEXT:    sth r6, 2(r4)
; CHECK-BE-NEXT:    addi r4, r4, 2
; CHECK-BE-NEXT:    bdnz .LBB2_1
; CHECK-BE-NEXT:  .LBB2_2: # %for.cond.cleanup
; CHECK-BE-NEXT:    addi r3, r1, 128
; CHECK-BE-NEXT:    bl test_arr
; CHECK-BE-NEXT:    nop
; CHECK-BE-NEXT:    addi r1, r1, 256
; CHECK-BE-NEXT:    ld r0, 16(r1)
; CHECK-BE-NEXT:    mtlr r0
; CHECK-BE-NEXT:    blr
entry:
  %Arr2 = alloca [64 x i16], align 2
  %i = alloca i32, align 4
  call void @llvm.lifetime.start.p0(i64 128, ptr %Arr2)
  call void @llvm.lifetime.start.p0(i64 4, ptr %i)
  store i32 0, ptr %i, align 4
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %entry
  %0 = load i32, ptr %i, align 4
  %cmp = icmp slt i32 %0, 64
  br i1 %cmp, label %for.body, label %for.cond.cleanup

for.cond.cleanup:                                 ; preds = %for.cond
  call void @llvm.lifetime.end.p0(i64 4, ptr %i)
  br label %for.end

for.body:                                         ; preds = %for.cond
  %1 = load i32, ptr %i, align 4
  %idxprom = sext i32 %1 to i64
  %arrayidx = getelementptr inbounds [64 x i8], ptr @Arr1, i64 0, i64 %idxprom
  %2 = load i8, ptr %arrayidx, align 1
  %conv = zext i8 %2 to i16
  %3 = load i32, ptr %i, align 4
  %idxprom1 = sext i32 %3 to i64
  %arrayidx2 = getelementptr inbounds [64 x i16], ptr %Arr2, i64 0, i64 %idxprom1
  store i16 %conv, ptr %arrayidx2, align 2
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %4 = load i32, ptr %i, align 4
  %inc = add nsw i32 %4, 1
  store i32 %inc, ptr %i, align 4
  br label %for.cond

for.end:                                          ; preds = %for.cond.cleanup
  call void @test_arr(ptr %Arr2)
  call void @llvm.lifetime.end.p0(i64 128, ptr %Arr2)
  ret void
}

declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) nounwind

declare void @test(ptr) nounwind
declare void @test1(ptr) nounwind
declare void @test_arr(ptr)

declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) nounwind