1; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static < %s \ 2; RUN: | FileCheck --check-prefixes=ALL,O32,O32-BE %s 3; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s \ 4; RUN: | FileCheck --check-prefixes=ALL,O32,O32-LE %s 5 6; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \ 7; RUN-TODO: | FileCheck --check-prefixes=ALL,O32 %s 8; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \ 9; RUN-TODO: | FileCheck --check-prefixes=ALL,O32 %s 10 11; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n32 < %s \ 12; RUN: | FileCheck --check-prefixes=ALL,N32,N32-BE %s 13; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n32 < %s \ 14; RUN: | FileCheck --check-prefixes=ALL,N32,N32-LE %s 15 16; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n64 < %s \ 17; RUN: | FileCheck --check-prefixes=ALL,N64,N64-BE %s 18; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n64 < %s \ 19; RUN: | FileCheck --check-prefixes=ALL,N64,N64-LE %s 20 21; Test struct returns for all ABI's and byte orders. 22 23@struct_byte = global {i8} zeroinitializer 24@struct_2byte = global {i8,i8} zeroinitializer 25@struct_3xi16 = global {[3 x i16]} zeroinitializer 26@struct_6xi32 = global {[6 x i32]} zeroinitializer 27@struct_128xi16 = global {[128 x i16]} zeroinitializer 28 29declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) 30 31define inreg {i8} @ret_struct_i8() nounwind { 32entry: 33 %0 = load volatile {i8}, {i8}* @struct_byte 34 ret {i8} %0 35} 36 37; ALL-LABEL: ret_struct_i8: 38; O32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte) 39; O32-DAG: lbu $2, %lo(struct_byte)([[R1]]) 40 41; N32-LE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte) 42; N32-LE-DAG: lb $2, %lo(struct_byte)([[R1]]) 43 44; N32-BE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte) 45; N32-BE-DAG: lb [[R2:\$[0-9]+]], %lo(struct_byte)([[R1]]) 46; N32-BE-DAG: dsll $2, [[R2]], 56 47 48; N64-LE-DAG: lb $2, %lo(struct_byte)(${{[0-9]+}}) 49 50; N64-BE-DAG: lb [[R1:\$[0-9]+]], %lo(struct_byte)(${{[0-9]+}}) 51; N64-BE-DAG: dsll $2, [[R1]], 56 52 53; This test is based on the way clang currently lowers {i8,i8} to {i16}. 54; FIXME: It should probably work for without any lowering too but this doesn't 55; work as expected. Each member gets mapped to a register rather than 56; packed into a single register. 57define inreg {i16} @ret_struct_i16() nounwind { 58entry: 59 %retval = alloca {i8,i8}, align 1 60 %0 = bitcast {i8,i8}* %retval to i8* 61 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* getelementptr inbounds ({i8,i8}, {i8,i8}* @struct_2byte, i32 0, i32 0), i64 2, i1 false) 62 %1 = bitcast {i8,i8}* %retval to {i16}* 63 %2 = load volatile {i16}, {i16}* %1 64 ret {i16} %2 65} 66 67; ALL-LABEL: ret_struct_i16: 68; O32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte) 69; O32-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) 70; O32-DAG: sh [[R2]], 0([[SP:\$sp]]) 71; O32-DAG: lhu $2, 0([[SP:\$sp]]) 72 73; N32-LE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte) 74; N32-LE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) 75; N32-LE-DAG: sh [[R2]], 8([[SP:\$sp]]) 76; N32-LE-DAG: lh $2, 8([[SP:\$sp]]) 77 78; N32-BE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte) 79; N32-BE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) 80; N32-BE-DAG: sh [[R2]], 8([[SP:\$sp]]) 81; N32-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]]) 82; N32-BE-DAG: dsll $2, [[R3]], 48 83 84; N64-LE-DAG: daddiu $[[R0:[0-9]+]], ${{[0-9]+}}, %hi(struct_2byte) 85; N64-LE-DAG: dsll [[R1:\$[0-9]]], $[[R0]], 16 86; N64-LE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]]) 87; N64-LE-DAG: sh [[R2]], 8([[SP:\$sp]]) 88; N64-LE-DAG: lh $2, 8([[SP:\$sp]]) 89 90; N64-BE-DAG: daddiu $[[R0:[0-9]+]], ${{[0-9]+}}, %hi(struct_2byte) 91; N64-BE-DAG: dsll $[[R1:[0-9]]], $[[R0]], 16 92; N64-BE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)($[[R1]]) 93; N64-BE-DAG: sh [[R2]], 8([[SP:\$sp]]) 94; N64-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]]) 95; N64-BE-DAG: dsll $2, [[R3]], 48 96 97; Ensure that structures bigger than 32-bits but smaller than 64-bits are 98; also returned in the upper bits on big endian targets. Previously, these were 99; missed by the CCPromoteToType and the shift didn't happen. 100define inreg {i48} @ret_struct_3xi16() nounwind { 101entry: 102 %0 = load volatile i48, i48* bitcast ({[3 x i16]}* @struct_3xi16 to i48*), align 2 103 %1 = insertvalue {i48} undef, i48 %0, 0 104 ret {i48} %1 105} 106 107; ALL-LABEL: ret_struct_3xi16: 108 109; O32-BE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) 110; O32-BE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) 111; O32-BE-DAG: lhu [[R1:\$[0-9]+]], 4([[PTR_LO]]) 112; O32-BE-DAG: lw [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) 113; O32-BE-DAG: sll [[R3:\$[0-9]+]], [[R2]], 16 114; O32-BE-DAG: or $3, [[R1]], [[R3]] 115; O32-BE-DAG: srl $2, [[R2]], 16 116 117; O32-LE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) 118; O32-LE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) 119; O32-LE-DAG: lhu $3, 4([[PTR_LO]]) 120; O32-LE-DAG: lw $2, %lo(struct_3xi16)([[PTR_HI]]) 121 122; N32-LE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) 123; N32-LE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) 124; N32-LE-DAG: lh [[R1:\$[0-9]+]], 4([[PTR_LO]]) 125; N32-LE-DAG: lwu [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) 126; N32-LE-DAG: dsll [[R3:\$[0-9]+]], [[R1]], 32 127; N32-LE-DAG: or $2, [[R2]], [[R3]] 128 129; N32-BE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) 130; N32-BE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) 131; N32-BE-DAG: lw [[R1:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) 132; N32-BE-DAG: dsll [[R2:\$[0-9]+]], [[R1]], 16 133; N32-BE-DAG: lhu [[R3:\$[0-9]+]], 4([[PTR_LO]]) 134; N32-BE-DAG: or [[R4:\$[0-9]+]], [[R3]], [[R2]] 135; N32-BE-DAG: dsll $2, [[R4]], 16 136 137; N64-LE-DAG: daddiu [[PTR:\$[0-9]+]], [[R0:\$[0-9]+]], %lo(struct_3xi16) 138; N64-LE-DAG: lh [[R1:\$[0-9]+]], 4([[PTR]]) 139; N64-LE-DAG: lwu [[R2:\$[0-9]+]], %lo(struct_3xi16)([[R0]]) 140; N64-LE-DAG: dsll [[R3:\$[0-9]+]], [[R1]], 32 141; N64-LE-DAG: or $2, [[R2]], [[R3]] 142 143; N64-BE-DAG: daddiu [[PTR:\$[0-9]+]], [[R0:\$[0-9]+]], %lo(struct_3xi16) 144; N64-BE-DAG: lw [[R1:\$[0-9]+]], %lo(struct_3xi16)([[R0]]) 145; N64-BE-DAG: dsll [[R2:\$[0-9]+]], [[R1]], 16 146; N64-BE-DAG: lhu [[R3:\$[0-9]+]], 4([[PTR]]) 147; N64-BE-DAG: or [[R4:\$[0-9]+]], [[R3]], [[R2]] 148; N64-BE-DAG: dsll $2, [[R4]], 16 149 150; Ensure that large structures (>128-bit) are returned indirectly. 151; We pick an extremely large structure so we don't have to match inlined memcpy's. 152define void @ret_struct_128xi16({[128 x i16]}* sret({[128 x i16]}) %returnval) { 153entry: 154 %0 = bitcast {[128 x i16]}* %returnval to i8* 155 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 %0, i8* align 2 bitcast ({[128 x i16]}* @struct_128xi16 to i8*), i64 256, i1 false) 156 ret void 157} 158 159; ALL-LABEL: ret_struct_128xi16: 160 161; sret pointer is already in $4 162; O32-DAG: lui [[PTR:\$[0-9]+]], %hi(struct_128xi16) 163; O32-DAG: addiu $5, [[PTR]], %lo(struct_128xi16) 164; O32: jal memcpy 165 166; sret pointer is already in $4 167; N32-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_128xi16) 168; N32-DAG: addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_128xi16) 169; N32: jal memcpy 170 171; sret pointer is already in $4 172; N64-DAG: lui ${{[0-9]}}, %highest(struct_128xi16) 173; N64: jal memcpy 174 175; Ensure that large structures (>128-bit) are returned indirectly. 176; This will generate inlined memcpy's anyway so pick the smallest large 177; structure 178; This time we let the backend lower the sret argument. 179define {[6 x i32]} @ret_struct_6xi32() { 180entry: 181 %0 = load volatile {[6 x i32]}, {[6 x i32]}* @struct_6xi32, align 2 182 ret {[6 x i32]} %0 183} 184 185; ALL-LABEL: ret_struct_6xi32: 186 187; sret pointer is already in $4 188; O32-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_6xi32) 189; O32-DAG: addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32) 190; O32-DAG: lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR]]) 191; O32-DAG: lw [[T1:\$[0-9]+]], 4([[PTR]]) 192; O32-DAG: lw [[T2:\$[0-9]+]], 8([[PTR]]) 193; O32-DAG: lw [[T3:\$[0-9]+]], 12([[PTR]]) 194; O32-DAG: lw [[T4:\$[0-9]+]], 16([[PTR]]) 195; O32-DAG: lw [[T5:\$[0-9]+]], 20([[PTR]]) 196; O32-DAG: sw [[T0]], 0($4) 197; O32-DAG: sw [[T1]], 4($4) 198; O32-DAG: sw [[T2]], 8($4) 199; O32-DAG: sw [[T3]], 12($4) 200; O32-DAG: sw [[T4]], 16($4) 201; O32-DAG: sw [[T5]], 20($4) 202 203; FIXME: This signext isn't necessary. Like integers, pointers are 204; but unlike integers, pointers cannot have the signext attribute. 205; In this case we don't have anywhere to put the signext either since 206; the sret argument is invented by the backend. 207; N32-DAG: sll [[RET_PTR:\$[0-9]+]], $4, 0 208; N32-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_6xi32) 209; N32-DAG: addiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32) 210; N32-DAG: lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR]]) 211; N32-DAG: lw [[T1:\$[0-9]+]], 4([[PTR]]) 212; N32-DAG: lw [[T2:\$[0-9]+]], 8([[PTR]]) 213; N32-DAG: lw [[T3:\$[0-9]+]], 12([[PTR]]) 214; N32-DAG: lw [[T4:\$[0-9]+]], 16([[PTR]]) 215; N32-DAG: lw [[T5:\$[0-9]+]], 20([[PTR]]) 216; N32-DAG: sw [[T0]], 0([[RET_PTR]]) 217; N32-DAG: sw [[T1]], 4([[RET_PTR]]) 218; N32-DAG: sw [[T2]], 8([[RET_PTR]]) 219; N32-DAG: sw [[T3]], 12([[RET_PTR]]) 220; N32-DAG: sw [[T4]], 16([[RET_PTR]]) 221; N32-DAG: sw [[T5]], 20([[RET_PTR]]) 222 223; sret pointer is already in $4 224; N64-DAG: lui [[PTR_HI:\$[0-9]+]], %highest(struct_6xi32) 225; N64-DAG: daddiu [[PTR:\$[0-9]+]], [[PTR_HI]], %lo(struct_6xi32) 226; N64-DAG: lw [[T1:\$[0-9]+]], 4([[PTR]]) 227; N64-DAG: lw [[T2:\$[0-9]+]], 8([[PTR]]) 228; N64-DAG: lw [[T3:\$[0-9]+]], 12([[PTR]]) 229; N64-DAG: lw [[T4:\$[0-9]+]], 16([[PTR]]) 230; N64-DAG: lw [[T5:\$[0-9]+]], 20([[PTR]]) 231; N64-DAG: lw [[T0:\$[0-9]+]], %lo(struct_6xi32)([[PTR_HI]]) 232; N64-DAG: sw [[T0]], 0($4) 233; N64-DAG: sw [[T1]], 4($4) 234; N64-DAG: sw [[T2]], 8($4) 235; N64-DAG: sw [[T3]], 12($4) 236; N64-DAG: sw [[T4]], 16($4) 237; N64-DAG: sw [[T5]], 20($4) 238