LLVM: lib/Target/PowerPC/PPCTLSDynamicCall.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

32

33using namespace llvm;

34

35#define DEBUG_TYPE "ppc-tls-dynamic-call"

36

37namespace {

39 static char ID;

41

43

44protected:

47 bool NeedFence = true;

50 bool Is64Bit = Subtarget.isPPC64();

51 bool IsAIX = Subtarget.isAIXABI();

52 bool IsLargeModel =

54 bool IsPCREL = false;

57

59 I != IE;) {

61 IsPCREL = isPCREL(MI);

62

63

64 bool IsTLSTPRelMI = MI.getOpcode() == PPC::GETtlsTpointer32AIX;

65 bool IsTLSLDAIXMI = (MI.getOpcode() == PPC::TLSLDAIX8 ||

66 MI.getOpcode() == PPC::TLSLDAIX);

67

68 if (MI.getOpcode() != PPC::ADDItlsgdLADDR &&

69 MI.getOpcode() != PPC::ADDItlsldLADDR &&

70 MI.getOpcode() != PPC::ADDItlsgdLADDR32 &&

71 MI.getOpcode() != PPC::ADDItlsldLADDR32 &&

72 MI.getOpcode() != PPC::TLSGDAIX &&

73 MI.getOpcode() != PPC::TLSGDAIX8 && !IsTLSTPRelMI && !IsPCREL &&

74 !IsTLSLDAIXMI) {

75

76

77

78

79 if (MI.getOpcode() == PPC::ADJCALLSTACKDOWN)

80 NeedFence = false;

81 else if (MI.getOpcode() == PPC::ADJCALLSTACKUP)

82 NeedFence = true;

83

84 ++I;

85 continue;

86 }

87

89

90 Register OutReg = MI.getOperand(0).getReg();

91 Register InReg = PPC::NoRegister;

92 Register GPR3 = Is64Bit ? PPC::X3 : PPC::R3;

93 Register GPR4 = Is64Bit ? PPC::X4 : PPC::R4;

94 if (!IsPCREL && !IsTLSTPRelMI)

95 InReg = MI.getOperand(1).getReg();

97

98 unsigned Opc1, Opc2;

99 switch (MI.getOpcode()) {

100 default:

102 case PPC::ADDItlsgdLADDR:

103 Opc1 = PPC::ADDItlsgdL;

104 Opc2 = PPC::GETtlsADDR;

105 break;

106 case PPC::ADDItlsldLADDR:

107 Opc1 = PPC::ADDItlsldL;

108 Opc2 = PPC::GETtlsldADDR;

109 break;

110 case PPC::ADDItlsgdLADDR32:

111 Opc1 = PPC::ADDItlsgdL32;

112 Opc2 = PPC::GETtlsADDR32;

113 break;

114 case PPC::ADDItlsldLADDR32:

115 Opc1 = PPC::ADDItlsldL32;

116 Opc2 = PPC::GETtlsldADDR32;

117 break;

118 case PPC::TLSLDAIX:

119

120

121 Opc2 = PPC::GETtlsMOD32AIX;

122 break;

123 case PPC::TLSLDAIX8:

124

125

126 Opc2 = PPC::GETtlsMOD64AIX;

127 break;

128 case PPC::TLSGDAIX8:

129

130

131 Opc2 = PPC::GETtlsADDR64AIX;

132 break;

133 case PPC::TLSGDAIX:

134

135

136 Opc2 = PPC::GETtlsADDR32AIX;

137 break;

138 case PPC::GETtlsTpointer32AIX:

139

140

141

142 Opc2 = PPC::GETtlsTpointer32AIX;

143 break;

144 case PPC::PADDI8pc:

145 assert(IsPCREL && "Expecting General/Local Dynamic PCRel");

146 Opc1 = PPC::PADDI8pc;

147 Opc2 = MI.getOperand(2).getTargetFlags() ==

149 ? PPC::GETtlsADDRPCREL

150 : PPC::GETtlsldADDRPCREL;

151 }

152

153

154

155

156

157

158

159 if (NeedFence) {

160 MBB.getParent()->getFrameInfo().setAdjustsStack(true);

163 }

164

165 if (IsAIX) {

166 if (IsTLSLDAIXMI) {

167

168

169

170

171

172

173

174

175 unsigned LDTocOp =

176 Is64Bit ? (IsLargeModel ? PPC::LDtocL : PPC::LDtoc)

177 : (IsLargeModel ? PPC::LWZtocL : PPC::LWZtoc);

178 if (RegInfo.use_empty(OutReg)) {

179 std::set<MachineInstr *> Uses;

180

182 Uses.insert(MO.getParent());

183

184

187 ++UseIter)

188 if (Uses.count(&*UseIter))

189 break;

190

191

192

193

194 if (UseIter != MBB.end()) {

195

196

197 std::set<MachineInstr *> LoadFromTocs;

199 if (MO.isReg() && MO.isUse()) {

200 Register MOReg = MO.getReg();

201 if (RegInfo.hasOneDef(MOReg)) {

203 RegInfo.getOneDef(MOReg)->getParent();

204

205

206

207

208 if (Temp == &MI && RegInfo.hasOneDef(InReg))

209 Temp = RegInfo.getOneDef(InReg)->getParent();

210 if (Temp->getOpcode() == LDTocOp)

211 LoadFromTocs.insert(Temp);

212 } else {

213

214 LoadFromTocs.clear();

215 break;

216 }

217 }

218

219

220

221

222 if (LoadFromTocs.size() == 2) {

225

226

227

229 IE = MBB.end();

230 I != IE; ++I)

231 if (LoadFromTocs.count(&*I)) {

235 TLSMLIter = I;

236 else

237 OffsetIter = I;

238 }

239

240

241

242 if (TLSMLIter != MBB.end() && OffsetIter != MBB.end())

243 OffsetIter->moveBefore(&*UseIter);

244 }

245 }

246 }

247

248

251

253 } else if (!IsTLSTPRelMI) {

254

255

256

258 .addReg(MI.getOperand(1).getReg());

260 .addReg(MI.getOperand(2).getReg());

262 } else

263

264

265

267 } else {

269 if (IsPCREL) {

271 } else {

272

273 assert(InReg != PPC::NoRegister && "Operand must be a register");

275 }

276

278

281 if (IsPCREL)

282 Call->addOperand(MI.getOperand(2));

283 else

284 Call->addOperand(MI.getOperand(3));

285 }

286 if (NeedFence)

288

291

292

293 ++I;

294 MI.removeFromParent();

295

297 }

298

300 }

301

302public:

304 return (MI.getOpcode() == PPC::PADDI8pc) &&

305 (MI.getOperand(2).getTargetFlags() ==

307 MI.getOperand(2).getTargetFlags() ==

309 }

310

311 bool runOnMachineFunction(MachineFunction &MF) override {

313

315

317 if (processBlock(B))

319

321 }

322

323 void getAnalysisUsage(AnalysisUsage &AU) const override {

327 }

328 };

329}

330

332 "PowerPC TLS Dynamic Call Fixup", false, false)

337

338char PPCTLSDynamicCall::ID = 0;

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

Remove Loads Into Fake Uses

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

FunctionPass class - This class is used to implement most global optimizations.

MachineInstrBundleIterator< MachineInstr > iterator

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

const PPCTargetMachine & getTargetMachine() const

Wrapper class representing virtual and physical registers.

CodeModel::Model getCodeModel() const

Returns the code model.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ MO_GOT_TLSLD_PCREL_FLAG

MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...

@ MO_GOT_TLSGD_PCREL_FLAG

MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

FunctionPass * createPPCTLSDynamicCallPass()

Definition PPCTLSDynamicCall.cpp:340

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.