Skip to content

Commit 956ca7e

Browse files
committed
[SPARC] Support reserving arbitrary general purpose registers
This adds support for marking arbitrary general purpose registers - except for those with special purpose (G0, I6-I7, O6-O7) - as reserved, as needed by some software like the Linux kernel.
1 parent 5237193 commit 956ca7e

File tree

12 files changed

+420
-2
lines changed

12 files changed

+420
-2
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5730,6 +5730,18 @@ def mvis3 : Flag<["-"], "mvis3">, Group<m_sparc_Features_Group>;
57305730
def mno_vis3 : Flag<["-"], "mno-vis3">, Group<m_sparc_Features_Group>;
57315731
def mhard_quad_float : Flag<["-"], "mhard-quad-float">, Group<m_sparc_Features_Group>;
57325732
def msoft_quad_float : Flag<["-"], "msoft-quad-float">, Group<m_sparc_Features_Group>;
5733+
foreach i = {1-7} in
5734+
def ffixed_g#i : Flag<["-"], "ffixed-g"#i>, Group<m_sparc_Features_Group>,
5735+
HelpText<"Reserve the G"#i#" register (SPARC only)">;
5736+
foreach i = {0-5} in
5737+
def ffixed_o#i : Flag<["-"], "ffixed-o"#i>, Group<m_sparc_Features_Group>,
5738+
HelpText<"Reserve the O"#i#" register (SPARC only)">;
5739+
foreach i = {0-7} in
5740+
def ffixed_l#i : Flag<["-"], "ffixed-l"#i>, Group<m_sparc_Features_Group>,
5741+
HelpText<"Reserve the L"#i#" register (SPARC only)">;
5742+
foreach i = {0-5} in
5743+
def ffixed_i#i : Flag<["-"], "ffixed-i"#i>, Group<m_sparc_Features_Group>,
5744+
HelpText<"Reserve the I"#i#" register (SPARC only)">;
57335745
} // let Flags = [TargetSpecific]
57345746

57355747
// M68k features flags

clang/lib/Driver/ToolChains/Arch/Sparc.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,85 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
178178
else
179179
Features.push_back("-hard-quad-float");
180180
}
181+
182+
if (Args.hasArg(options::OPT_ffixed_g1))
183+
Features.push_back("+reserve-g1");
184+
185+
if (Args.hasArg(options::OPT_ffixed_g2))
186+
Features.push_back("+reserve-g2");
187+
188+
if (Args.hasArg(options::OPT_ffixed_g3))
189+
Features.push_back("+reserve-g3");
190+
191+
if (Args.hasArg(options::OPT_ffixed_g4))
192+
Features.push_back("+reserve-g4");
193+
194+
if (Args.hasArg(options::OPT_ffixed_g5))
195+
Features.push_back("+reserve-g5");
196+
197+
if (Args.hasArg(options::OPT_ffixed_g6))
198+
Features.push_back("+reserve-g6");
199+
200+
if (Args.hasArg(options::OPT_ffixed_g7))
201+
Features.push_back("+reserve-g7");
202+
203+
if (Args.hasArg(options::OPT_ffixed_o0))
204+
Features.push_back("+reserve-o0");
205+
206+
if (Args.hasArg(options::OPT_ffixed_o1))
207+
Features.push_back("+reserve-o1");
208+
209+
if (Args.hasArg(options::OPT_ffixed_o2))
210+
Features.push_back("+reserve-o2");
211+
212+
if (Args.hasArg(options::OPT_ffixed_o3))
213+
Features.push_back("+reserve-o3");
214+
215+
if (Args.hasArg(options::OPT_ffixed_o4))
216+
Features.push_back("+reserve-o4");
217+
218+
if (Args.hasArg(options::OPT_ffixed_o5))
219+
Features.push_back("+reserve-o5");
220+
221+
if (Args.hasArg(options::OPT_ffixed_l0))
222+
Features.push_back("+reserve-l0");
223+
224+
if (Args.hasArg(options::OPT_ffixed_l1))
225+
Features.push_back("+reserve-l1");
226+
227+
if (Args.hasArg(options::OPT_ffixed_l2))
228+
Features.push_back("+reserve-l2");
229+
230+
if (Args.hasArg(options::OPT_ffixed_l3))
231+
Features.push_back("+reserve-l3");
232+
233+
if (Args.hasArg(options::OPT_ffixed_l4))
234+
Features.push_back("+reserve-l4");
235+
236+
if (Args.hasArg(options::OPT_ffixed_l5))
237+
Features.push_back("+reserve-l5");
238+
239+
if (Args.hasArg(options::OPT_ffixed_l6))
240+
Features.push_back("+reserve-l6");
241+
242+
if (Args.hasArg(options::OPT_ffixed_l7))
243+
Features.push_back("+reserve-l7");
244+
245+
if (Args.hasArg(options::OPT_ffixed_i0))
246+
Features.push_back("+reserve-i0");
247+
248+
if (Args.hasArg(options::OPT_ffixed_i1))
249+
Features.push_back("+reserve-i1");
250+
251+
if (Args.hasArg(options::OPT_ffixed_i2))
252+
Features.push_back("+reserve-i2");
253+
254+
if (Args.hasArg(options::OPT_ffixed_i3))
255+
Features.push_back("+reserve-i3");
256+
257+
if (Args.hasArg(options::OPT_ffixed_i4))
258+
Features.push_back("+reserve-i4");
259+
260+
if (Args.hasArg(options::OPT_ffixed_i5))
261+
Features.push_back("+reserve-i5");
181262
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// RUN: %clang --target=sparc-none-gnu -ffixed-g1 -### %s 2> %t
2+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G1 < %t %s
3+
// CHECK-FIXED-G1: "-target-feature" "+reserve-g1"
4+
5+
// RUN: %clang --target=sparc-none-gnu -ffixed-g2 -### %s 2> %t
6+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G2 < %t %s
7+
// CHECK-FIXED-G2: "-target-feature" "+reserve-g2"
8+
9+
// RUN: %clang --target=sparc-none-gnu -ffixed-g3 -### %s 2> %t
10+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G3 < %t %s
11+
// CHECK-FIXED-G3: "-target-feature" "+reserve-g3"
12+
13+
// RUN: %clang --target=sparc-none-gnu -ffixed-g4 -### %s 2> %t
14+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G4 < %t %s
15+
// CHECK-FIXED-G4: "-target-feature" "+reserve-g4"
16+
17+
// RUN: %clang --target=sparc-none-gnu -ffixed-g5 -### %s 2> %t
18+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G5 < %t %s
19+
// CHECK-FIXED-G5: "-target-feature" "+reserve-g5"
20+
21+
// RUN: %clang --target=sparc-none-gnu -ffixed-g6 -### %s 2> %t
22+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G6 < %t %s
23+
// CHECK-FIXED-G6: "-target-feature" "+reserve-g6"
24+
25+
// RUN: %clang --target=sparc-none-gnu -ffixed-g7 -### %s 2> %t
26+
// RUN: FileCheck --check-prefix=CHECK-FIXED-G7 < %t %s
27+
// CHECK-FIXED-G7: "-target-feature" "+reserve-g7"
28+
29+
// RUN: %clang --target=sparc-none-gnu -ffixed-o0 -### %s 2> %t
30+
// RUN: FileCheck --check-prefix=CHECK-FIXED-O0 < %t %s
31+
// CHECK-FIXED-O0: "-target-feature" "+reserve-o0"
32+
33+
// RUN: %clang --target=sparc-none-gnu -ffixed-o1 -### %s 2> %t
34+
// RUN: FileCheck --check-prefix=CHECK-FIXED-O1 < %t %s
35+
// CHECK-FIXED-O1: "-target-feature" "+reserve-o1"
36+
37+
// RUN: %clang --target=sparc-none-gnu -ffixed-o2 -### %s 2> %t
38+
// RUN: FileCheck --check-prefix=CHECK-FIXED-O2 < %t %s
39+
// CHECK-FIXED-O2: "-target-feature" "+reserve-o2"
40+
41+
// RUN: %clang --target=sparc-none-gnu -ffixed-o3 -### %s 2> %t
42+
// RUN: FileCheck --check-prefix=CHECK-FIXED-O3 < %t %s
43+
// CHECK-FIXED-O3: "-target-feature" "+reserve-o3"
44+
45+
// RUN: %clang --target=sparc-none-gnu -ffixed-o4 -### %s 2> %t
46+
// RUN: FileCheck --check-prefix=CHECK-FIXED-O4 < %t %s
47+
// CHECK-FIXED-O4: "-target-feature" "+reserve-o4"
48+
49+
// RUN: %clang --target=sparc-none-gnu -ffixed-o5 -### %s 2> %t
50+
// RUN: FileCheck --check-prefix=CHECK-FIXED-O5 < %t %s
51+
// CHECK-FIXED-O5: "-target-feature" "+reserve-o5"
52+
53+
// RUN: %clang --target=sparc-none-gnu -ffixed-l0 -### %s 2> %t
54+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L0 < %t %s
55+
// CHECK-FIXED-L0: "-target-feature" "+reserve-l0"
56+
57+
// RUN: %clang --target=sparc-none-gnu -ffixed-l1 -### %s 2> %t
58+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L1 < %t %s
59+
// CHECK-FIXED-L1: "-target-feature" "+reserve-l1"
60+
61+
// RUN: %clang --target=sparc-none-gnu -ffixed-l2 -### %s 2> %t
62+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L2 < %t %s
63+
// CHECK-FIXED-L2: "-target-feature" "+reserve-l2"
64+
65+
// RUN: %clang --target=sparc-none-gnu -ffixed-l3 -### %s 2> %t
66+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L3 < %t %s
67+
// CHECK-FIXED-L3: "-target-feature" "+reserve-l3"
68+
69+
// RUN: %clang --target=sparc-none-gnu -ffixed-l4 -### %s 2> %t
70+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L4 < %t %s
71+
// CHECK-FIXED-L4: "-target-feature" "+reserve-l4"
72+
73+
// RUN: %clang --target=sparc-none-gnu -ffixed-l5 -### %s 2> %t
74+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L5 < %t %s
75+
// CHECK-FIXED-L5: "-target-feature" "+reserve-l5"
76+
77+
// RUN: %clang --target=sparc-none-gnu -ffixed-l6 -### %s 2> %t
78+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L6 < %t %s
79+
// CHECK-FIXED-L6: "-target-feature" "+reserve-l6"
80+
81+
// RUN: %clang --target=sparc-none-gnu -ffixed-l7 -### %s 2> %t
82+
// RUN: FileCheck --check-prefix=CHECK-FIXED-L7 < %t %s
83+
// CHECK-FIXED-L7: "-target-feature" "+reserve-l7"
84+
85+
// RUN: %clang --target=sparc-none-gnu -ffixed-i0 -### %s 2> %t
86+
// RUN: FileCheck --check-prefix=CHECK-FIXED-I0 < %t %s
87+
// CHECK-FIXED-I0: "-target-feature" "+reserve-i0"
88+
89+
// RUN: %clang --target=sparc-none-gnu -ffixed-i1 -### %s 2> %t
90+
// RUN: FileCheck --check-prefix=CHECK-FIXED-I1 < %t %s
91+
// CHECK-FIXED-I1: "-target-feature" "+reserve-i1"
92+
93+
// RUN: %clang --target=sparc-none-gnu -ffixed-i2 -### %s 2> %t
94+
// RUN: FileCheck --check-prefix=CHECK-FIXED-I2 < %t %s
95+
// CHECK-FIXED-I2: "-target-feature" "+reserve-i2"
96+
97+
// RUN: %clang --target=sparc-none-gnu -ffixed-i3 -### %s 2> %t
98+
// RUN: FileCheck --check-prefix=CHECK-FIXED-I3 < %t %s
99+
// CHECK-FIXED-I3: "-target-feature" "+reserve-i3"
100+
101+
// RUN: %clang --target=sparc-none-gnu -ffixed-i4 -### %s 2> %t
102+
// RUN: FileCheck --check-prefix=CHECK-FIXED-I4 < %t %s
103+
// CHECK-FIXED-I4: "-target-feature" "+reserve-i4"
104+
105+
// RUN: %clang --target=sparc-none-gnu -ffixed-i5 -### %s 2> %t
106+
// RUN: FileCheck --check-prefix=CHECK-FIXED-I5 < %t %s
107+
// CHECK-FIXED-I5: "-target-feature" "+reserve-i5"
108+
109+
// Test multiple of reserve-* options together.
110+
// RUN: %clang --target=sparc-none-gnu \
111+
// RUN: -ffixed-g1 \
112+
// RUN: -ffixed-o2 \
113+
// RUN: -ffixed-l3 \
114+
// RUN: -ffixed-i4 \
115+
// RUN: -### %s 2> %t
116+
// RUN: FileCheck \
117+
// RUN: --check-prefix=CHECK-FIXED-G1 \
118+
// RUN: --check-prefix=CHECK-FIXED-O2 \
119+
// RUN: --check-prefix=CHECK-FIXED-L3 \
120+
// RUN: --check-prefix=CHECK-FIXED-I4 \
121+
// RUN: < %t %s
122+
123+
// Test all reserve-* options together.
124+
// RUN: %clang --target=sparc-none-gnu \
125+
// RUN: -ffixed-g1 \
126+
// RUN: -ffixed-g2 \
127+
// RUN: -ffixed-g3 \
128+
// RUN: -ffixed-g4 \
129+
// RUN: -ffixed-g5 \
130+
// RUN: -ffixed-g6 \
131+
// RUN: -ffixed-g7 \
132+
// RUN: -ffixed-o0 \
133+
// RUN: -ffixed-o1 \
134+
// RUN: -ffixed-o2 \
135+
// RUN: -ffixed-o3 \
136+
// RUN: -ffixed-o4 \
137+
// RUN: -ffixed-o5 \
138+
// RUN: -ffixed-l0 \
139+
// RUN: -ffixed-l1 \
140+
// RUN: -ffixed-l2 \
141+
// RUN: -ffixed-l3 \
142+
// RUN: -ffixed-l4 \
143+
// RUN: -ffixed-l5 \
144+
// RUN: -ffixed-l6 \
145+
// RUN: -ffixed-l7 \
146+
// RUN: -ffixed-i0 \
147+
// RUN: -ffixed-i1 \
148+
// RUN: -ffixed-i2 \
149+
// RUN: -ffixed-i3 \
150+
// RUN: -ffixed-i4 \
151+
// RUN: -ffixed-i5 \
152+
// RUN: -### %s 2> %t
153+
// RUN: FileCheck \
154+
// RUN: --check-prefix=CHECK-FIXED-G1 \
155+
// RUN: --check-prefix=CHECK-FIXED-G2 \
156+
// RUN: --check-prefix=CHECK-FIXED-G3 \
157+
// RUN: --check-prefix=CHECK-FIXED-G4 \
158+
// RUN: --check-prefix=CHECK-FIXED-G5 \
159+
// RUN: --check-prefix=CHECK-FIXED-G6 \
160+
// RUN: --check-prefix=CHECK-FIXED-G7 \
161+
// RUN: --check-prefix=CHECK-FIXED-O0 \
162+
// RUN: --check-prefix=CHECK-FIXED-O1 \
163+
// RUN: --check-prefix=CHECK-FIXED-O2 \
164+
// RUN: --check-prefix=CHECK-FIXED-O3 \
165+
// RUN: --check-prefix=CHECK-FIXED-O4 \
166+
// RUN: --check-prefix=CHECK-FIXED-O5 \
167+
// RUN: --check-prefix=CHECK-FIXED-L0 \
168+
// RUN: --check-prefix=CHECK-FIXED-L1 \
169+
// RUN: --check-prefix=CHECK-FIXED-L2 \
170+
// RUN: --check-prefix=CHECK-FIXED-L3 \
171+
// RUN: --check-prefix=CHECK-FIXED-L4 \
172+
// RUN: --check-prefix=CHECK-FIXED-L5 \
173+
// RUN: --check-prefix=CHECK-FIXED-L6 \
174+
// RUN: --check-prefix=CHECK-FIXED-L7 \
175+
// RUN: --check-prefix=CHECK-FIXED-I0 \
176+
// RUN: --check-prefix=CHECK-FIXED-I1 \
177+
// RUN: --check-prefix=CHECK-FIXED-I2 \
178+
// RUN: --check-prefix=CHECK-FIXED-I3 \
179+
// RUN: --check-prefix=CHECK-FIXED-I4 \
180+
// RUN: --check-prefix=CHECK-FIXED-I5 \
181+
// RUN: < %t %s

llvm/lib/Target/Sparc/Sparc.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ def FeatureSoftFloat : SubtargetFeature<"soft-float", "UseSoftFloat", "true",
6565
//==== Features added predmoninantly for LEON subtarget support
6666
include "LeonFeatures.td"
6767

68+
//==== Register allocation tweaks needed by some low-level software
69+
foreach i = {1-7} in
70+
def FeatureReserveG#i : SubtargetFeature<"reserve-g"#i, "ReserveGRegister["#i#"]", "true",
71+
"Reserve G"#i#", making it unavailable as a GPR">;
72+
foreach i = {0-5} in
73+
def FeatureReserveO#i : SubtargetFeature<"reserve-o"#i, "ReserveORegister["#i#"]", "true",
74+
"Reserve O"#i#", making it unavailable as a GPR">;
75+
foreach i = {0-7} in
76+
def FeatureReserveL#i : SubtargetFeature<"reserve-l"#i, "ReserveLRegister["#i#"]", "true",
77+
"Reserve L"#i#", making it unavailable as a GPR">;
78+
foreach i = {0-5} in
79+
def FeatureReserveI#i : SubtargetFeature<"reserve-i"#i, "ReserveIRegister["#i#"]", "true",
80+
"Reserve I"#i#", making it unavailable as a GPR">;
81+
6882
//===----------------------------------------------------------------------===//
6983
// Register File, Calling Conv, Instruction Descriptions
7084
//===----------------------------------------------------------------------===//

llvm/lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
805805
bool &isTailCall = CLI.IsTailCall;
806806
CallingConv::ID CallConv = CLI.CallConv;
807807
bool isVarArg = CLI.IsVarArg;
808+
MachineFunction &MF = DAG.getMachineFunction();
808809

809810
// Analyze operands of the call, assigning locations to each operand.
810811
SmallVector<CCValAssign, 16> ArgLocs;
@@ -1055,6 +1056,10 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
10551056
((hasReturnsTwice)
10561057
? TRI->getRTCallPreservedMask(CallConv)
10571058
: TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv));
1059+
1060+
if (TRI->isAnyArgRegReserved(MF))
1061+
TRI->emitReservedArgRegCallError(MF);
1062+
10581063
assert(Mask && "Missing call preserved mask for calling convention");
10591064
Ops.push_back(DAG.getRegisterMask(Mask));
10601065

@@ -1125,6 +1130,19 @@ Register SparcTargetLowering::getRegisterByName(const char* RegName, LLT VT,
11251130
.Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7)
11261131
.Default(0);
11271132

1133+
const SparcRegisterInfo *MRI = Subtarget->getRegisterInfo();
1134+
unsigned DwarfRegNum = MRI->getDwarfRegNum(Reg, false);
1135+
if (!MRI->isReservedReg(MF, Reg)) {
1136+
bool IsG = DwarfRegNum < 8, IsO = DwarfRegNum >= 8 && DwarfRegNum < 16,
1137+
IsL = DwarfRegNum >= 16 && DwarfRegNum < 24, IsI = DwarfRegNum >= 24;
1138+
unsigned NumInBank = DwarfRegNum % 8;
1139+
if ((IsG && !Subtarget->isGRegisterReserved(NumInBank)) ||
1140+
(IsO && !Subtarget->isORegisterReserved(NumInBank)) ||
1141+
(IsL && !Subtarget->isLRegisterReserved(NumInBank)) ||
1142+
(IsI && !Subtarget->isIRegisterReserved(NumInBank)))
1143+
Reg = 0;
1144+
}
1145+
11281146
if (Reg)
11291147
return Reg;
11301148

@@ -1189,6 +1207,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
11891207
SDLoc DL = CLI.DL;
11901208
SDValue Chain = CLI.Chain;
11911209
auto PtrVT = getPointerTy(DAG.getDataLayout());
1210+
MachineFunction &MF = DAG.getMachineFunction();
11921211

11931212
// Analyze operands of the call, assigning locations to each operand.
11941213
SmallVector<CCValAssign, 16> ArgLocs;
@@ -1372,6 +1391,10 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
13721391
((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CLI.CallConv)
13731392
: TRI->getCallPreservedMask(DAG.getMachineFunction(),
13741393
CLI.CallConv));
1394+
1395+
if (TRI->isAnyArgRegReserved(MF))
1396+
TRI->emitReservedArgRegCallError(MF);
1397+
13751398
assert(Mask && "Missing call preserved mask for calling convention");
13761399
Ops.push_back(DAG.getRegisterMask(Mask));
13771400

0 commit comments

Comments
 (0)