Skip to content

Commit 4394e68

Browse files
committed
Implement ISD::VAARG lowering on PPC32.
llvm-svn: 134005
1 parent 2a31eb4 commit 4394e68

File tree

2 files changed

+290
-5
lines changed

2 files changed

+290
-5
lines changed

llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
215215
setOperationAction(ISD::VASTART , MVT::Other, Custom);
216216

217217
// VAARG is custom lowered with the 32-bit SVR4 ABI.
218-
if ( TM.getSubtarget<PPCSubtarget>().isSVR4ABI()
219-
&& !TM.getSubtarget<PPCSubtarget>().isPPC64())
218+
if (TM.getSubtarget<PPCSubtarget>().isSVR4ABI()
219+
&& !TM.getSubtarget<PPCSubtarget>().isPPC64()) {
220220
setOperationAction(ISD::VAARG, MVT::Other, Custom);
221-
else
221+
setOperationAction(ISD::VAARG, MVT::i64, Custom);
222+
} else
222223
setOperationAction(ISD::VAARG, MVT::Other, Expand);
223224

224225
// Use the default implementation.
@@ -1262,9 +1263,110 @@ SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
12621263

12631264
SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG,
12641265
const PPCSubtarget &Subtarget) const {
1266+
SDNode *Node = Op.getNode();
1267+
EVT VT = Node->getValueType(0);
1268+
EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
1269+
SDValue InChain = Node->getOperand(0);
1270+
SDValue VAListPtr = Node->getOperand(1);
1271+
const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
1272+
DebugLoc dl = Node->getDebugLoc();
1273+
1274+
assert(!Subtarget.isPPC64() && "LowerVAARG is PPC32 only");
1275+
1276+
// gpr_index
1277+
SDValue GprIndex = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, InChain,
1278+
VAListPtr, MachinePointerInfo(SV), MVT::i8,
1279+
false, false, 0);
1280+
InChain = GprIndex.getValue(1);
1281+
1282+
if (VT == MVT::i64) {
1283+
// Check if GprIndex is even
1284+
SDValue GprAnd = DAG.getNode(ISD::AND, dl, MVT::i32, GprIndex,
1285+
DAG.getConstant(1, MVT::i32));
1286+
SDValue CC64 = DAG.getSetCC(dl, MVT::i32, GprAnd,
1287+
DAG.getConstant(0, MVT::i32), ISD::SETNE);
1288+
SDValue GprIndexPlusOne = DAG.getNode(ISD::ADD, dl, MVT::i32, GprIndex,
1289+
DAG.getConstant(1, MVT::i32));
1290+
// Align GprIndex to be even if it isn't
1291+
GprIndex = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC64, GprIndexPlusOne,
1292+
GprIndex);
1293+
}
1294+
1295+
// fpr index is 1 byte after gpr
1296+
SDValue FprPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr,
1297+
DAG.getConstant(1, MVT::i32));
1298+
1299+
// fpr
1300+
SDValue FprIndex = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, InChain,
1301+
FprPtr, MachinePointerInfo(SV), MVT::i8,
1302+
false, false, 0);
1303+
InChain = FprIndex.getValue(1);
1304+
1305+
SDValue RegSaveAreaPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr,
1306+
DAG.getConstant(8, MVT::i32));
1307+
1308+
SDValue OverflowAreaPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAListPtr,
1309+
DAG.getConstant(4, MVT::i32));
12651310

1266-
llvm_unreachable("VAARG not yet implemented for the SVR4 ABI!");
1267-
return SDValue(); // Not reached
1311+
// areas
1312+
SDValue OverflowArea = DAG.getLoad(MVT::i32, dl, InChain, OverflowAreaPtr,
1313+
MachinePointerInfo(), false, false, 0);
1314+
InChain = OverflowArea.getValue(1);
1315+
1316+
SDValue RegSaveArea = DAG.getLoad(MVT::i32, dl, InChain, RegSaveAreaPtr,
1317+
MachinePointerInfo(), false, false, 0);
1318+
InChain = RegSaveArea.getValue(1);
1319+
1320+
// select overflow_area if index > 8
1321+
SDValue CC = DAG.getSetCC(dl, MVT::i32, VT.isInteger() ? GprIndex : FprIndex,
1322+
DAG.getConstant(8, MVT::i32), ISD::SETLT);
1323+
1324+
SDValue Area = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC, RegSaveArea,
1325+
OverflowArea);
1326+
1327+
// adjustment constant gpr_index * 4/8
1328+
SDValue RegConstant = DAG.getNode(ISD::MUL, dl, MVT::i32,
1329+
VT.isInteger() ? GprIndex : FprIndex,
1330+
DAG.getConstant(VT.isInteger() ? 4 : 8,
1331+
MVT::i32));
1332+
1333+
// OurReg = RegSaveArea + RegConstant
1334+
SDValue OurReg = DAG.getNode(ISD::ADD, dl, PtrVT, RegSaveArea,
1335+
RegConstant);
1336+
1337+
// Floating types are 32 bytes into RegSaveArea
1338+
if (VT.isFloatingPoint())
1339+
OurReg = DAG.getNode(ISD::ADD, dl, PtrVT, OurReg,
1340+
DAG.getConstant(32, MVT::i32));
1341+
1342+
// increase {f,g}pr_index by 1 (or 2 if VT is i64)
1343+
SDValue IndexPlus1 = DAG.getNode(ISD::ADD, dl, MVT::i32,
1344+
VT.isInteger() ? GprIndex : FprIndex,
1345+
DAG.getConstant(VT == MVT::i64 ? 2 : 1,
1346+
MVT::i32));
1347+
1348+
InChain = DAG.getTruncStore(InChain, dl, IndexPlus1,
1349+
VT.isInteger() ? VAListPtr : FprPtr,
1350+
MachinePointerInfo(SV),
1351+
MVT::i8, false, false, 0);
1352+
1353+
// determine if we should load from reg_save_area or overflow_area
1354+
SDValue Result = DAG.getNode(ISD::SELECT, dl, PtrVT, CC, OurReg, OverflowArea);
1355+
1356+
// increase overflow_area by 4/8 if gpr/fpr > 8
1357+
SDValue OverflowAreaPlusN = DAG.getNode(ISD::ADD, dl, PtrVT, OverflowArea,
1358+
DAG.getConstant(VT.isInteger() ? 4 : 8,
1359+
MVT::i32));
1360+
1361+
OverflowArea = DAG.getNode(ISD::SELECT, dl, MVT::i32, CC, OverflowArea,
1362+
OverflowAreaPlusN);
1363+
1364+
InChain = DAG.getTruncStore(InChain, dl, OverflowArea,
1365+
OverflowAreaPtr,
1366+
MachinePointerInfo(),
1367+
MVT::i32, false, false, 0);
1368+
1369+
return DAG.getLoad(VT, dl, InChain, Result, MachinePointerInfo(), false, false, 0);
12681370
}
12691371

12701372
SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op,
@@ -4429,11 +4531,27 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
44294531
void PPCTargetLowering::ReplaceNodeResults(SDNode *N,
44304532
SmallVectorImpl<SDValue>&Results,
44314533
SelectionDAG &DAG) const {
4534+
const TargetMachine &TM = getTargetMachine();
44324535
DebugLoc dl = N->getDebugLoc();
44334536
switch (N->getOpcode()) {
44344537
default:
44354538
assert(false && "Do not know how to custom type legalize this operation!");
44364539
return;
4540+
case ISD::VAARG: {
4541+
if (!TM.getSubtarget<PPCSubtarget>().isSVR4ABI()
4542+
|| TM.getSubtarget<PPCSubtarget>().isPPC64())
4543+
return;
4544+
4545+
EVT VT = N->getValueType(0);
4546+
4547+
if (VT == MVT::i64) {
4548+
SDValue NewNode = LowerVAARG(SDValue(N, 1), DAG, PPCSubTarget);
4549+
4550+
Results.push_back(NewNode);
4551+
Results.push_back(NewNode.getValue(1));
4552+
}
4553+
return;
4554+
}
44374555
case ISD::FP_ROUND_INREG: {
44384556
assert(N->getValueType(0) == MVT::ppcf128);
44394557
assert(N->getOperand(0).getValueType() == MVT::ppcf128);
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
; RUN: llc -O0 < %s | FileCheck %s
2+
;ModuleID = 'test.c'
3+
target datalayout = "E-p:32:32:32-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"
4+
target triple = "powerpc-unknown-freebsd9.0"
5+
6+
%struct.__va_list_tag = type { i8, i8, i16, i8*, i8* }
7+
8+
@var1 = common global i64 0, align 8
9+
@var2 = common global double 0.0, align 8
10+
@var3 = common global i32 0, align 4
11+
12+
define void @ppcvaargtest(%struct.__va_list_tag* %ap) nounwind {
13+
entry:
14+
%x = va_arg %struct.__va_list_tag* %ap, i64; Get from r5,r6
15+
; CHECK: lbz 4, 0(3)
16+
; CHECK-NEXT: lwz 5, 4(3)
17+
; CHECK-NEXT: rlwinm 6, 4, 0, 31, 31
18+
; CHECK-NEXT: cmplwi 0, 6, 0
19+
; CHECK-NEXT: addi 6, 4, 1
20+
; CHECK-NEXT: stw 3, -4(1)
21+
; CHECK-NEXT: stw 6, -8(1)
22+
; CHECK-NEXT: stw 4, -12(1)
23+
; CHECK-NEXT: stw 5, -16(1)
24+
; CHECK-NEXT: bne 0, .LBB0_2
25+
; CHECK-NEXT: # BB#1: # %entry
26+
; CHECK-NEXT: lwz 3, -12(1)
27+
; CHECK-NEXT: stw 3, -8(1)
28+
; CHECK-NEXT: .LBB0_2: # %entry
29+
; CHECK-NEXT: lwz 3, -8(1)
30+
; CHECK-NEXT: lwz 4, -4(1)
31+
; CHECK-NEXT: lwz 5, 8(4)
32+
; CHECK-NEXT: slwi 6, 3, 2
33+
; CHECK-NEXT: addi 7, 3, 2
34+
; CHECK-NEXT: cmpwi 0, 3, 8
35+
; CHECK-NEXT: lwz 3, -16(1)
36+
; CHECK-NEXT: addi 8, 3, 4
37+
; CHECK-NEXT: add 5, 5, 6
38+
; CHECK-NEXT: mfcr 0 # cr0
39+
; CHECK-NEXT: stw 0, -20(1)
40+
; CHECK-NEXT: stw 5, -24(1)
41+
; CHECK-NEXT: stw 3, -28(1)
42+
; CHECK-NEXT: stw 7, -32(1)
43+
; CHECK-NEXT: stw 8, -36(1)
44+
; CHECK-NEXT: blt 0, .LBB0_4
45+
; CHECK-NEXT: # BB#3: # %entry
46+
; CHECK-NEXT: lwz 3, -36(1)
47+
; CHECK-NEXT: stw 3, -28(1)
48+
; CHECK-NEXT: .LBB0_4: # %entry
49+
; CHECK-NEXT: lwz 3, -28(1)
50+
; CHECK-NEXT: lwz 4, -32(1)
51+
; CHECK-NEXT: lwz 5, -4(1)
52+
; CHECK-NEXT: stb 4, 0(5)
53+
; CHECK-NEXT: lwz 4, -24(1)
54+
; CHECK-NEXT: lwz 0, -20(1)
55+
; CHECK-NEXT: mtcrf 128, 0
56+
; CHECK-NEXT: stw 3, -40(1)
57+
; CHECK-NEXT: stw 4, -44(1)
58+
; CHECK-NEXT: blt 0, .LBB0_6
59+
; CHECK-NEXT: # BB#5: # %entry
60+
; CHECK-NEXT: lwz 3, -16(1)
61+
; CHECK-NEXT: stw 3, -44(1)
62+
; CHECK-NEXT: .LBB0_6: # %entry
63+
; CHECK-NEXT: lwz 3, -44(1)
64+
; CHECK-NEXT: lwz 4, -40(1)
65+
; CHECK-NEXT: lwz 5, -4(1)
66+
; CHECK-NEXT: stw 4, 4(5)
67+
store i64 %x, i64* @var1, align 8
68+
; CHECK-NEXT: lis 4, var1@ha
69+
; CHECK-NEXT: lwz 6, 4(3)
70+
; CHECK-NEXT: lwz 3, 0(3)
71+
; CHECK-NEXT: la 7, var1@l(4)
72+
; CHECK-NEXT: stw 3, var1@l(4)
73+
; CHECK-NEXT: stw 6, 4(7)
74+
%y = va_arg %struct.__va_list_tag* %ap, double; From f1
75+
; CHECK-NEXT: lbz 3, 1(5)
76+
; CHECK-NEXT: lwz 4, 4(5)
77+
; CHECK-NEXT: lwz 6, 8(5)
78+
; CHECK-NEXT: slwi 7, 3, 3
79+
; CHECK-NEXT: add 6, 6, 7
80+
; CHECK-NEXT: addi 7, 3, 1
81+
; CHECK-NEXT: cmpwi 0, 3, 8
82+
; CHECK-NEXT: addi 3, 4, 8
83+
; CHECK-NEXT: addi 6, 6, 32
84+
; CHECK-NEXT: mr 8, 4
85+
; CHECK-NEXT: mfcr 0 # cr0
86+
; CHECK-NEXT: stw 0, -48(1)
87+
; CHECK-NEXT: stw 4, -52(1)
88+
; CHECK-NEXT: stw 6, -56(1)
89+
; CHECK-NEXT: stw 7, -60(1)
90+
; CHECK-NEXT: stw 3, -64(1)
91+
; CHECK-NEXT: stw 8, -68(1)
92+
; CHECK-NEXT: blt 0, .LBB0_8
93+
; CHECK-NEXT: # BB#7: # %entry
94+
; CHECK-NEXT: lwz 3, -64(1)
95+
; CHECK-NEXT: stw 3, -68(1)
96+
; CHECK-NEXT: .LBB0_8: # %entry
97+
; CHECK-NEXT: lwz 3, -68(1)
98+
; CHECK-NEXT: lwz 4, -60(1)
99+
; CHECK-NEXT: lwz 5, -4(1)
100+
; CHECK-NEXT: stb 4, 1(5)
101+
; CHECK-NEXT: lwz 4, -56(1)
102+
; CHECK-NEXT: lwz 0, -48(1)
103+
; CHECK-NEXT: mtcrf 128, 0
104+
; CHECK-NEXT: stw 4, -72(1)
105+
; CHECK-NEXT: stw 3, -76(1)
106+
; CHECK-NEXT: blt 0, .LBB0_10
107+
; CHECK-NEXT: # BB#9: # %entry
108+
; CHECK-NEXT: lwz 3, -52(1)
109+
; CHECK-NEXT: stw 3, -72(1)
110+
; CHECK-NEXT: .LBB0_10: # %entry
111+
; CHECK-NEXT: lwz 3, -72(1)
112+
; CHECK-NEXT: lwz 4, -76(1)
113+
; CHECK-NEXT: lwz 5, -4(1)
114+
; CHECK-NEXT: stw 4, 4(5)
115+
; CHECK-NEXT: lfd 0, 0(3)
116+
store double %y, double* @var2, align 8
117+
; CHECK-NEXT: lis 3, var2@ha
118+
; CHECK-NEXT: stfd 0, var2@l(3)
119+
%z = va_arg %struct.__va_list_tag* %ap, i32; From r7
120+
; CHECK-NEXT: lbz 3, 0(5)
121+
; CHECK-NEXT: lwz 4, 4(5)
122+
; CHECK-NEXT: lwz 6, 8(5)
123+
; CHECK-NEXT: slwi 7, 3, 2
124+
; CHECK-NEXT: addi 8, 3, 1
125+
; CHECK-NEXT: cmpwi 0, 3, 8
126+
; CHECK-NEXT: addi 3, 4, 4
127+
; CHECK-NEXT: add 6, 6, 7
128+
; CHECK-NEXT: mr 7, 4
129+
; CHECK-NEXT: stw 6, -80(1)
130+
; CHECK-NEXT: stw 8, -84(1)
131+
; CHECK-NEXT: stw 3, -88(1)
132+
; CHECK-NEXT: stw 4, -92(1)
133+
; CHECK-NEXT: stw 7, -96(1)
134+
; CHECK-NEXT: mfcr 0 # cr0
135+
; CHECK-NEXT: stw 0, -100(1)
136+
; CHECK-NEXT: blt 0, .LBB0_12
137+
; CHECK-NEXT: # BB#11: # %entry
138+
; CHECK-NEXT: lwz 3, -88(1)
139+
; CHECK-NEXT: stw 3, -96(1)
140+
; CHECK-NEXT: .LBB0_12: # %entry
141+
; CHECK-NEXT: lwz 3, -96(1)
142+
; CHECK-NEXT: lwz 4, -84(1)
143+
; CHECK-NEXT: lwz 5, -4(1)
144+
; CHECK-NEXT: stb 4, 0(5)
145+
; CHECK-NEXT: lwz 4, -80(1)
146+
; CHECK-NEXT: lwz 0, -100(1)
147+
; CHECK-NEXT: mtcrf 128, 0
148+
; CHECK-NEXT: stw 4, -104(1)
149+
; CHECK-NEXT: stw 3, -108(1)
150+
; CHECK-NEXT: blt 0, .LBB0_14
151+
; CHECK-NEXT: # BB#13: # %entry
152+
; CHECK-NEXT: lwz 3, -92(1)
153+
; CHECK-NEXT: stw 3, -104(1)
154+
; CHECK-NEXT: .LBB0_14: # %entry
155+
; CHECK-NEXT: lwz 3, -104(1)
156+
; CHECK-NEXT: lwz 4, -108(1)
157+
; CHECK-NEXT: lwz 5, -4(1)
158+
; CHECK-NEXT: stw 4, 4(5)
159+
; CHECK-NEXT: lwz 3, 0(3)
160+
store i32 %z, i32* @var3, align 4
161+
; CHECK-NEXT: lis 4, var3@ha
162+
; CHECK-NEXT: stw 3, var3@l(4)
163+
ret void
164+
; CHECK-NEXT: stw 5, -112(1)
165+
; CHECK-NEXT: blr
166+
}
167+

0 commit comments

Comments
 (0)