llvm.org GIT mirror llvm / 37900c5
This patch addresses a PPC64 ELF issue with passing parameters consisting of structs having size 3, 5, 6, or 7. Such a struct must be passed and received as right-justified within its register or memory slot. The problem is only present for structs that are passed in registers. Previously, as part of a patch handling all structs of size less than 8, I added logic to rotate the incoming register so that the struct was left- justified prior to storing the whole register. This was incorrect because the address of the parameter had already been adjusted earlier to point to the right-adjusted value in the storage slot. Essentially I had accidentally accounted for the right-adjustment twice. In this patch, I removed the incorrect logic and reorganized the code to make the flow clearer. The removal of the rotates changes the expected code generation, so test case structsinregs.ll has been modified to reflect this. I also added a new test case, jaggedstructs.ll, to demonstrate that structs of these sizes can now be properly received and passed. I've built and tested the code on powerpc64-unknown-linux-gnu with no new regressions. I also ran the GCC compatibility test suite and verified that earlier problems with these structs are now resolved, with no new regressions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166680 91177308-0d34-0410-b5e6-96231b3b80d8 Bill Schmidt 8 years ago
3 changed file(s) with 80 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
20832083 int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset, true);
20842084 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
20852085 InVals.push_back(FIN);
2086 if (ObjSize==1 || ObjSize==2 || ObjSize==4) {
2086
2087 if (ObjSize < 8) {
20872088 if (GPR_idx != Num_GPR_Regs) {
2088 unsigned VReg;
2089 VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
2089 unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
20902090 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
2091 EVT ObjType = (ObjSize == 1 ? MVT::i8 :
2092 (ObjSize == 2 ? MVT::i16 : MVT::i32));
2093 SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN,
2094 MachinePointerInfo(FuncArg,
2095 CurArgOffset),
2096 ObjType, false, false, 0);
2091 SDValue Store;
2092
2093 if (ObjSize==1 || ObjSize==2 || ObjSize==4) {
2094 EVT ObjType = (ObjSize == 1 ? MVT::i8 :
2095 (ObjSize == 2 ? MVT::i16 : MVT::i32));
2096 Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN,
2097 MachinePointerInfo(FuncArg, CurArgOffset),
2098 ObjType, false, false, 0);
2099 } else {
2100 // For sizes that don't fit a truncating store (3, 5, 6, 7),
2101 // store the whole register as-is to the parameter save area
2102 // slot. The address of the parameter was already calculated
2103 // above (InVals.push_back(FIN)) to be the right-justified
2104 // offset within the slot. For this store, we need a new
2105 // frame index that points at the beginning of the slot.
2106 int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true);
2107 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
2108 Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
2109 MachinePointerInfo(FuncArg, ArgOffset),
2110 false, false, 0);
2111 }
2112
20972113 MemOps.push_back(Store);
20982114 ++GPR_idx;
20992115 }
2100
2116 // Whether we copied from a register or not, advance the offset
2117 // into the parameter save area by a full doubleword.
21012118 ArgOffset += PtrByteSize;
2102
21032119 continue;
21042120 }
2121
21052122 for (unsigned j = 0; j < ArgSize; j += PtrByteSize) {
21062123 // Store whatever pieces of the object are in registers
21072124 // to memory. ArgOffset will be the address of the beginning
21122129 int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true);
21132130 SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
21142131 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
2115 SDValue Shifted = Val;
2116
2117 // For 64-bit SVR4, small structs come in right-adjusted.
2118 // Shift them left so the following logic works as expected.
2119 if (ObjSize < 8) {
2120 SDValue ShiftAmt = DAG.getConstant(64 - 8 * ObjSize, PtrVT);
2121 Shifted = DAG.getNode(ISD::SHL, dl, PtrVT, Val, ShiftAmt);
2122 }
2123
2124 SDValue Store = DAG.getStore(Val.getValue(1), dl, Shifted, FIN,
2132 SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
21252133 MachinePointerInfo(FuncArg, ArgOffset),
21262134 false, false, 0);
21272135 MemOps.push_back(Store);
0 ; RUN: llc -mcpu=pwr7 -O0 < %s | FileCheck %s
1
2 ; This tests receiving and re-passing parameters consisting of structures
3 ; of size 3, 5, 6, and 7. They are to be found/placed right-adjusted in
4 ; the parameter registers.
5
6 target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64"
7 target triple = "powerpc64-unknown-linux-gnu"
8
9 %struct.S3 = type { [3 x i8] }
10 %struct.S5 = type { [5 x i8] }
11 %struct.S6 = type { [6 x i8] }
12 %struct.S7 = type { [7 x i8] }
13
14 define void @test(%struct.S3* byval %s3, %struct.S5* byval %s5, %struct.S6* byval %s6, %struct.S7* byval %s7) nounwind {
15 entry:
16 call void @check(%struct.S3* byval %s3, %struct.S5* byval %s5, %struct.S6* byval %s6, %struct.S7* byval %s7)
17 ret void
18 }
19
20 ; CHECK: std 6, 216(1)
21 ; CHECK: std 5, 208(1)
22 ; CHECK: std 4, 200(1)
23 ; CHECK: std 3, 192(1)
24 ; CHECK: lbz {{[0-9]+}}, 199(1)
25 ; CHECK: stb {{[0-9]+}}, 55(1)
26 ; CHECK: lhz {{[0-9]+}}, 197(1)
27 ; CHECK: sth {{[0-9]+}}, 53(1)
28 ; CHECK: lbz {{[0-9]+}}, 207(1)
29 ; CHECK: stb {{[0-9]+}}, 63(1)
30 ; CHECK: lwz {{[0-9]+}}, 203(1)
31 ; CHECK: stw {{[0-9]+}}, 59(1)
32 ; CHECK: lhz {{[0-9]+}}, 214(1)
33 ; CHECK: sth {{[0-9]+}}, 70(1)
34 ; CHECK: lwz {{[0-9]+}}, 210(1)
35 ; CHECK: stw {{[0-9]+}}, 66(1)
36 ; CHECK: lbz {{[0-9]+}}, 223(1)
37 ; CHECK: stb {{[0-9]+}}, 79(1)
38 ; CHECK: lhz {{[0-9]+}}, 221(1)
39 ; CHECK: sth {{[0-9]+}}, 77(1)
40 ; CHECK: lwz {{[0-9]+}}, 217(1)
41 ; CHECK: stw {{[0-9]+}}, 73(1)
42 ; CHECK: ld 6, 72(1)
43 ; CHECK: ld 5, 64(1)
44 ; CHECK: ld 4, 56(1)
45 ; CHECK: ld 3, 48(1)
46
47 declare void @check(%struct.S3* byval, %struct.S5* byval, %struct.S6* byval, %struct.S7* byval)
187187 %add13 = add nsw i32 %add11, %6
188188 ret i32 %add13
189189
190 ; CHECK: sldi 9, 9, 8
191 ; CHECK: sldi 8, 8, 16
192 ; CHECK: sldi 7, 7, 24
193 ; CHECK: sldi 5, 5, 40
194 ; CHECK: stw 6, 76(1)
195 ; CHECK: sth 4, 62(1)
196 ; CHECK: stb 3, 55(1)
197190 ; CHECK: std 9, 96(1)
198191 ; CHECK: std 8, 88(1)
199192 ; CHECK: std 7, 80(1)
193 ; CHECK: stw 6, 76(1)
200194 ; CHECK: std 5, 64(1)
195 ; CHECK: sth 4, 62(1)
196 ; CHECK: stb 3, 55(1)
201197 ; CHECK: lbz {{[0-9]+}}, 85(1)
202198 ; CHECK: lbz {{[0-9]+}}, 86(1)
203199 ; CHECK: lbz {{[0-9]+}}, 83(1)