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: $a0_64 24; CHECK-NEXT: move $4, $1 25; CHECK-NEXT: jal use_sret 26; CHECK-NEXT: nop 27; CHECK-NEXT: ld $ra, 40($sp) # 8-byte Folded Reload 28; CHECK-NEXT: daddiu $sp, $sp, 48 29; CHECK-NEXT: jr $ra 30; CHECK-NEXT: nop 31start: 32 %0 = call { i32, i128, i64 } @implicit_sret_decl() 33 %1 = extractvalue { i32, i128, i64 } %0, 0 34 %2 = extractvalue { i32, i128, i64 } %0, 1 35 %3 = extractvalue { i32, i128, i64 } %0, 2 36 call void @use_sret(i32 %1, i128 %2, i64 %3) 37 ret void 38} 39 40define internal { i32, i128, i64 } @implicit_sret_impl() unnamed_addr nounwind { 41; CHECK-LABEL: implicit_sret_impl: 42; CHECK: # %bb.0: 43; CHECK-NEXT: # kill: def $at_64 killed $a0_64 44; CHECK-NEXT: daddiu $1, $zero, 20 45; CHECK-NEXT: sd $1, 16($4) 46; CHECK-NEXT: daddiu $1, $zero, 0 47; CHECK-NEXT: sd $zero, 8($4) 48; CHECK-NEXT: daddiu $1, $zero, 30 49; CHECK-NEXT: sd $1, 24($4) 50; CHECK-NEXT: addiu $1, $zero, 10 51; CHECK-NEXT: sw $1, 0($4) 52; CHECK-NEXT: jr $ra 53; CHECK-NEXT: nop 54 ret { i32, i128, i64 } { i32 10, i128 20, i64 30 } 55} 56 57declare dso_local { i32, i32, i32, i32, i32, i32 } @implicit_sret_decl2() unnamed_addr 58declare dso_local void @use_sret2(i32, i32, i32) unnamed_addr 59define internal void @test2() unnamed_addr nounwind { 60; CHECK-LABEL: test2: 61; CHECK: # %bb.0: # %start 62; CHECK-NEXT: daddiu $sp, $sp, -32 63; CHECK-NEXT: sd $ra, 24($sp) # 8-byte Folded Spill 64; CHECK-NEXT: daddiu $4, $sp, 0 65; CHECK-NEXT: jal implicit_sret_decl2 66; CHECK-NEXT: nop 67; CHECK-NEXT: lw $1, 20($sp) 68; CHECK-NEXT: lw $2, 12($sp) 69; CHECK-NEXT: lw $3, 4($sp) 70; CHECK-NEXT: # implicit-def: $a0_64 71; CHECK-NEXT: move $4, $3 72; CHECK-NEXT: # implicit-def: $a1_64 73; CHECK-NEXT: move $5, $2 74; CHECK-NEXT: # implicit-def: $a2_64 75; CHECK-NEXT: move $6, $1 76; CHECK-NEXT: jal use_sret2 77; CHECK-NEXT: nop 78; CHECK-NEXT: ld $ra, 24($sp) # 8-byte Folded Reload 79; CHECK-NEXT: daddiu $sp, $sp, 32 80; CHECK-NEXT: jr $ra 81; CHECK-NEXT: nop 82start: 83 %0 = call { i32, i32, i32, i32, i32, i32 } @implicit_sret_decl2() 84 %1 = extractvalue { i32, i32, i32, i32, i32, i32 } %0, 1 85 %2 = extractvalue { i32, i32, i32, i32, i32, i32 } %0, 3 86 %3 = extractvalue { i32, i32, i32, i32, i32, i32 } %0, 5 87 call void @use_sret2(i32 %1, i32 %2, i32 %3) 88 ret void 89} 90 91 92define internal { i32, i32, i32, i32, i32, i32 } @implicit_sret_impl2() unnamed_addr nounwind { 93; CHECK-LABEL: implicit_sret_impl2: 94; CHECK: # %bb.0: 95; CHECK-NEXT: # kill: def $at_64 killed $a0_64 96; CHECK-NEXT: addiu $1, $zero, 6 97; CHECK-NEXT: sw $1, 20($4) 98; CHECK-NEXT: addiu $1, $zero, 5 99; CHECK-NEXT: sw $1, 16($4) 100; CHECK-NEXT: addiu $1, $zero, 4 101; CHECK-NEXT: sw $1, 12($4) 102; CHECK-NEXT: addiu $1, $zero, 3 103; CHECK-NEXT: sw $1, 8($4) 104; CHECK-NEXT: addiu $1, $zero, 2 105; CHECK-NEXT: sw $1, 4($4) 106; CHECK-NEXT: addiu $1, $zero, 1 107; CHECK-NEXT: sw $1, 0($4) 108; CHECK-NEXT: jr $ra 109; CHECK-NEXT: nop 110 ret { i32, i32, i32, i32, i32, i32 } { i32 1, i32 2, i32 3, i32 4, i32 5, i32 6 } 111} 112