1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=mips64-unknown-freebsd -O0 -o - %s | FileCheck %s 3 4; Previously SelectionDAGBuilder would always set alignment to 1 for hidden sret 5; parameters so we were generating ldl+ldr/lwl+lwr to load those values even 6; though we know that they are aligned (since we allocated an aligned frame index) 7 8declare dso_local void @use_sret(i32, i128, i64) unnamed_addr 9declare dso_local { i32, i128, i64 } @implicit_sret_decl() unnamed_addr 10 11define internal void @test() unnamed_addr nounwind { 12; CHECK-LABEL: test: 13; CHECK: # %bb.0: # %start 14; CHECK-NEXT: daddiu $sp, $sp, -48 15; CHECK-NEXT: sd $ra, 40($sp) # 8-byte Folded Spill 16; CHECK-NEXT: daddiu $4, $sp, 8 17; CHECK-NEXT: jal implicit_sret_decl 18; CHECK-NEXT: nop 19; CHECK-NEXT: ld $6, 24($sp) 20; CHECK-NEXT: ld $5, 16($sp) 21; CHECK-NEXT: ld $7, 32($sp) 22; CHECK-NEXT: lw $1, 8($sp) 23; CHECK-NEXT: # implicit-def: $v0_64 24; CHECK-NEXT: move $2, $1 25; CHECK-NEXT: move $4, $2 26; CHECK-NEXT: jal use_sret 27; CHECK-NEXT: nop 28; CHECK-NEXT: ld $ra, 40($sp) # 8-byte Folded Reload 29; CHECK-NEXT: daddiu $sp, $sp, 48 30; CHECK-NEXT: jr $ra 31; CHECK-NEXT: nop 32start: 33 %0 = call { i32, i128, i64 } @implicit_sret_decl() 34 %1 = extractvalue { i32, i128, i64 } %0, 0 35 %2 = extractvalue { i32, i128, i64 } %0, 1 36 %3 = extractvalue { i32, i128, i64 } %0, 2 37 call void @use_sret(i32 %1, i128 %2, i64 %3) 38 ret void 39} 40 41define internal { i32, i128, i64 } @implicit_sret_impl() unnamed_addr nounwind { 42; CHECK-LABEL: implicit_sret_impl: 43; CHECK: # %bb.0: 44; CHECK-NEXT: move $1, $4 45; CHECK-NEXT: daddiu $2, $zero, 20 46; CHECK-NEXT: sd $2, 16($4) 47; CHECK-NEXT: daddiu $2, $zero, 0 48; CHECK-NEXT: sd $zero, 8($4) 49; CHECK-NEXT: daddiu $3, $zero, 30 50; CHECK-NEXT: sd $3, 24($4) 51; CHECK-NEXT: addiu $3, $zero, 10 52; CHECK-NEXT: sw $3, 0($4) 53; CHECK-NEXT: jr $ra 54; CHECK-NEXT: nop 55 ret { i32, i128, i64 } { i32 10, i128 20, i64 30 } 56} 57 58declare dso_local { i32, i32, i32, i32, i32, i32 } @implicit_sret_decl2() unnamed_addr 59declare dso_local void @use_sret2(i32, i32, i32) unnamed_addr 60define internal void @test2() unnamed_addr nounwind { 61; CHECK-LABEL: test2: 62; CHECK: # %bb.0: # %start 63; CHECK-NEXT: daddiu $sp, $sp, -32 64; CHECK-NEXT: sd $ra, 24($sp) # 8-byte Folded Spill 65; CHECK-NEXT: daddiu $4, $sp, 0 66; CHECK-NEXT: jal implicit_sret_decl2 67; CHECK-NEXT: nop 68; CHECK-NEXT: lw $1, 20($sp) 69; CHECK-NEXT: lw $2, 12($sp) 70; CHECK-NEXT: lw $3, 4($sp) 71; CHECK-NEXT: # implicit-def: $a0_64 72; CHECK-NEXT: move $4, $3 73; CHECK-NEXT: # implicit-def: $v1_64 74; CHECK-NEXT: move $3, $2 75; CHECK-NEXT: # implicit-def: $v0_64 76; CHECK-NEXT: move $2, $1 77; CHECK-NEXT: move $5, $3 78; CHECK-NEXT: move $6, $2 79; CHECK-NEXT: jal use_sret2 80; CHECK-NEXT: nop 81; CHECK-NEXT: ld $ra, 24($sp) # 8-byte Folded Reload 82; CHECK-NEXT: daddiu $sp, $sp, 32 83; CHECK-NEXT: jr $ra 84; CHECK-NEXT: nop 85start: 86 %0 = call { i32, i32, i32, i32, i32, i32 } @implicit_sret_decl2() 87 %1 = extractvalue { i32, i32, i32, i32, i32, i32 } %0, 1 88 %2 = extractvalue { i32, i32, i32, i32, i32, i32 } %0, 3 89 %3 = extractvalue { i32, i32, i32, i32, i32, i32 } %0, 5 90 call void @use_sret2(i32 %1, i32 %2, i32 %3) 91 ret void 92} 93 94 95define internal { i32, i32, i32, i32, i32, i32 } @implicit_sret_impl2() unnamed_addr nounwind { 96; CHECK-LABEL: implicit_sret_impl2: 97; CHECK: # %bb.0: 98; CHECK-NEXT: move $1, $4 99; CHECK-NEXT: addiu $2, $zero, 6 100; CHECK-NEXT: sw $2, 20($4) 101; CHECK-NEXT: addiu $2, $zero, 5 102; CHECK-NEXT: sw $2, 16($4) 103; CHECK-NEXT: addiu $2, $zero, 4 104; CHECK-NEXT: sw $2, 12($4) 105; CHECK-NEXT: addiu $2, $zero, 3 106; CHECK-NEXT: sw $2, 8($4) 107; CHECK-NEXT: addiu $2, $zero, 2 108; CHECK-NEXT: sw $2, 4($4) 109; CHECK-NEXT: addiu $2, $zero, 1 110; CHECK-NEXT: sw $2, 0($4) 111; CHECK-NEXT: jr $ra 112; CHECK-NEXT: nop 113 ret { i32, i32, i32, i32, i32, i32 } { i32 1, i32 2, i32 3, i32 4, i32 5, i32 6 } 114} 115