From de90aa00ac7f4e2ad5ead35cc0118a7666991fb7 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Fri, 24 Oct 2014 13:09:19 +0000 Subject: [PATCH] [mips] For N32/N64, structs must be passed in the upper bits of a register. Summary: Most structs were fixed by r218451 but those of between >32-bits and <64-bits remained broken since they were not marked with [ASZ]ExtUpper. This patch fixes the remaining cases by using CCPromoteToUpperBitsInType on i64's in addition to i32 and smaller. Reviewers: vmedic Reviewed By: vmedic Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D5963 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220556 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsCallingConv.td | 4 +- test/CodeGen/Mips/cconv/return-struct.ll | 54 ++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index bb45d4195ec..9e47338f09a 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -137,9 +137,9 @@ def RetCC_MipsN : CallingConv<[ // both little and big-endian targets. When passing in registers, this // requires that big-endian targets shift the value into the upper bits. CCIfSubtarget<"isLittle()", - CCIfType<[i8, i16, i32], CCIfInReg>>>, + CCIfType<[i8, i16, i32, i64], CCIfInReg>>>, CCIfSubtargetNot<"isLittle()", - CCIfType<[i8, i16, i32], CCIfInReg>>>, + CCIfType<[i8, i16, i32, i64], CCIfInReg>>>, // i32 are returned in registers V0, V1 CCIfType<[i32], CCAssignToReg<[V0, V1]>>, diff --git a/test/CodeGen/Mips/cconv/return-struct.ll b/test/CodeGen/Mips/cconv/return-struct.ll index 5252766121b..688aa3dbaa0 100644 --- a/test/CodeGen/Mips/cconv/return-struct.ll +++ b/test/CodeGen/Mips/cconv/return-struct.ll @@ -14,6 +14,7 @@ @struct_byte = global {i8} zeroinitializer @struct_2byte = global {i8,i8} zeroinitializer +@struct_3xi16 = global {[3 x i16]} zeroinitializer declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) @@ -82,3 +83,56 @@ entry: ; N64-BE-DAG: sh [[R2]], 8([[SP:\$sp]]) ; N64-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]]) ; N64-BE-DAG: dsll $2, [[R3]], 48 + +; Ensure that structures bigger than 32-bits but smaller than 64-bits are +; also returned in the upper bits on big endian targets. Previously, these were +; missed by the CCPromoteToType and the shift didn't happen. +define inreg {i48} @ret_struct_3xi16() nounwind { +entry: + %0 = load volatile i48* bitcast ({[3 x i16]}* @struct_3xi16 to i48*), align 2 + %1 = insertvalue {i48} undef, i48 %0, 0 + ret {i48} %1 +} + +; ALL-LABEL: ret_struct_3xi16: + +; O32-BE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; O32-BE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; O32-BE-DAG: lhu [[R1:\$[0-9]+]], 4([[PTR_LO]]) +; O32-BE-DAG: lw [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) +; O32-BE-DAG: sll [[R3:\$[0-9]+]], [[R2]], 16 +; O32-BE-DAG: or $3, [[R1]], [[R3]] +; O32-BE-DAG: srl $2, [[R2]], 16 + +; O32-LE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; O32-LE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; O32-LE-DAG: lhu $3, 4([[PTR_LO]]) +; O32-LE-DAG: lw $2, %lo(struct_3xi16)([[PTR_HI]]) + +; N32-LE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; N32-LE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; N32-LE-DAG: lh [[R1:\$[0-9]+]], 4([[PTR_LO]]) +; N32-LE-DAG: lwu [[R2:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) +; N32-LE-DAG: dsll [[R3:\$[0-9]+]], [[R1]], 32 +; N32-LE-DAG: or $2, [[R2]], [[R3]] + +; N32-BE-DAG: lui [[PTR_HI:\$[0-9]+]], %hi(struct_3xi16) +; N32-BE-DAG: addiu [[PTR_LO:\$[0-9]+]], [[PTR_HI]], %lo(struct_3xi16) +; N32-BE-DAG: lw [[R1:\$[0-9]+]], %lo(struct_3xi16)([[PTR_HI]]) +; N32-BE-DAG: dsll [[R2:\$[0-9]+]], [[R1]], 16 +; N32-BE-DAG: lhu [[R3:\$[0-9]+]], 4([[PTR_LO]]) +; N32-BE-DAG: or [[R4:\$[0-9]+]], [[R3]], [[R2]] +; N32-BE-DAG: dsll $2, [[R4]], 16 + +; N64-LE-DAG: ld [[PTR:\$[0-9]+]], %got_disp(struct_3xi16)($1) +; N64-LE-DAG: lh [[R1:\$[0-9]+]], 4([[PTR]]) +; N64-LE-DAG: lwu [[R2:\$[0-9]+]], 0([[PTR]]) +; N64-LE-DAG: dsll [[R3:\$[0-9]+]], [[R1]], 32 +; N64-LE-DAG: or $2, [[R2]], [[R3]] + +; N64-BE-DAG: ld [[PTR:\$[0-9]+]], %got_disp(struct_3xi16)($1) +; N64-BE-DAG: lw [[R1:\$[0-9]+]], 0([[PTR]]) +; N64-BE-DAG: dsll [[R2:\$[0-9]+]], [[R1]], 16 +; N64-BE-DAG: lhu [[R3:\$[0-9]+]], 4([[PTR]]) +; N64-BE-DAG: or [[R4:\$[0-9]+]], [[R3]], [[R2]] +; N32-BE-DAG: dsll $2, [[R4]], 16 -- 2.34.1