blob: 2d1d4272a77ed1b57bcb168f942cf31d94a0c50c [file] [log] [blame]
Chandler Carruth69940402007-08-04 01:51:18 +00001//===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chandler Carruth69940402007-08-04 01:51:18 +00007//
8//===----------------------------------------------------------------------===//
9//
Matt Arsenault3f493222013-07-20 17:46:00 +000010// This file implements the auto-upgrade helper functions
Chandler Carruth69940402007-08-04 01:51:18 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/AutoUpgrade.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000015#include "llvm/IR/Constants.h"
16#include "llvm/IR/Function.h"
17#include "llvm/IR/IRBuilder.h"
18#include "llvm/IR/Instruction.h"
19#include "llvm/IR/IntrinsicInst.h"
20#include "llvm/IR/LLVMContext.h"
21#include "llvm/IR/Module.h"
Bill Wendlingc82a61c2011-08-25 23:22:40 +000022#include "llvm/Support/CFG.h"
Chandler Carruth06cb8ed2012-06-29 12:38:19 +000023#include "llvm/Support/CallSite.h"
Torok Edwinc25e7582009-07-11 20:10:48 +000024#include "llvm/Support/ErrorHandling.h"
Anton Korobeynikovae9f3a32008-02-20 11:08:44 +000025#include <cstring>
Chandler Carruth69940402007-08-04 01:51:18 +000026using namespace llvm;
27
Nadav Rotem3c98ce22012-06-10 18:42:51 +000028// Upgrade the declarations of the SSE4.1 functions whose arguments have
29// changed their type from v4f32 to v2i64.
30static bool UpgradeSSE41Function(Function* F, Intrinsic::ID IID,
31 Function *&NewFn) {
32 // Check whether this is an old version of the function, which received
33 // v4f32 arguments.
34 Type *Arg0Type = F->getFunctionType()->getParamType(0);
35 if (Arg0Type != VectorType::get(Type::getFloatTy(F->getContext()), 4))
36 return false;
37
38 // Yes, it's old, replace it with new version.
39 F->setName(F->getName() + ".old");
40 NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
41 return true;
42}
Chandler Carruth69940402007-08-04 01:51:18 +000043
Evan Chengf9b83fc2007-12-17 22:33:23 +000044static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
Chandler Carruth69940402007-08-04 01:51:18 +000045 assert(F && "Illegal to upgrade a non-existent Function.");
46
Chandler Carruth69940402007-08-04 01:51:18 +000047 // Quickly eliminate it, if it's not a candidate.
Chris Lattner747fddd2011-06-18 18:56:39 +000048 StringRef Name = F->getName();
49 if (Name.size() <= 8 || !Name.startswith("llvm."))
Evan Chengf9b83fc2007-12-17 22:33:23 +000050 return false;
Chris Lattner747fddd2011-06-18 18:56:39 +000051 Name = Name.substr(5); // Strip off "llvm."
Chris Lattnerb5dd9de2011-11-27 08:42:07 +000052
Chris Lattner747fddd2011-06-18 18:56:39 +000053 switch (Name[0]) {
Chandler Carruth69940402007-08-04 01:51:18 +000054 default: break;
Joel Jones06a6a302012-07-13 23:25:25 +000055 case 'a': {
56 if (Name.startswith("arm.neon.vclz")) {
57 Type* args[2] = {
Matt Arsenault3f493222013-07-20 17:46:00 +000058 F->arg_begin()->getType(),
Joel Jones06a6a302012-07-13 23:25:25 +000059 Type::getInt1Ty(F->getContext())
60 };
61 // Can't use Intrinsic::getDeclaration here as it adds a ".i1" to
62 // the end of the name. Change name from llvm.arm.neon.vclz.* to
63 // llvm.ctlz.*
64 FunctionType* fType = FunctionType::get(F->getReturnType(), args, false);
Matt Arsenault3f493222013-07-20 17:46:00 +000065 NewFn = Function::Create(fType, F->getLinkage(),
Joel Jones06a6a302012-07-13 23:25:25 +000066 "llvm.ctlz." + Name.substr(14), F->getParent());
67 return true;
68 }
Joel Jones7c82e6a2012-07-18 00:02:16 +000069 if (Name.startswith("arm.neon.vcnt")) {
70 NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop,
71 F->arg_begin()->getType());
72 return true;
73 }
Joel Jones06a6a302012-07-13 23:25:25 +000074 break;
75 }
Chandler Carruthccbf1e32011-12-12 04:26:04 +000076 case 'c': {
Chandler Carruthccbf1e32011-12-12 04:26:04 +000077 if (Name.startswith("ctlz.") && F->arg_size() == 1) {
78 F->setName(Name + ".old");
Chandler Carrutha56f5582011-12-12 10:57:20 +000079 NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
80 F->arg_begin()->getType());
Chandler Carruthccbf1e32011-12-12 04:26:04 +000081 return true;
82 }
83 if (Name.startswith("cttz.") && F->arg_size() == 1) {
84 F->setName(Name + ".old");
Chandler Carrutha56f5582011-12-12 10:57:20 +000085 NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::cttz,
86 F->arg_begin()->getType());
Chandler Carruthccbf1e32011-12-12 04:26:04 +000087 return true;
88 }
89 break;
90 }
Matt Arsenaultc4a8c072013-10-07 18:06:48 +000091 case 'o':
92 // We only need to change the name to match the mangling including the
93 // address space.
94 if (F->arg_size() == 2 && Name.startswith("objectsize.")) {
95 Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() };
96 if (F->getName() != Intrinsic::getName(Intrinsic::objectsize, Tys)) {
97 F->setName(Name + ".old");
98 NewFn = Intrinsic::getDeclaration(F->getParent(),
99 Intrinsic::objectsize, Tys);
100 return true;
101 }
102 }
103 break;
104
Craig Toppere058d272012-02-03 06:10:55 +0000105 case 'x': {
106 if (Name.startswith("x86.sse2.pcmpeq.") ||
107 Name.startswith("x86.sse2.pcmpgt.") ||
108 Name.startswith("x86.avx2.pcmpeq.") ||
Craig Toppera963c812012-04-18 05:24:00 +0000109 Name.startswith("x86.avx2.pcmpgt.") ||
Craig Topper189bce42012-05-08 06:58:15 +0000110 Name.startswith("x86.avx.vpermil.") ||
111 Name == "x86.avx.movnt.dq.256" ||
112 Name == "x86.avx.movnt.pd.256" ||
Craig Topperc29106b2012-06-09 16:46:13 +0000113 Name == "x86.avx.movnt.ps.256" ||
114 (Name.startswith("x86.xop.vpcom") && F->arg_size() == 2)) {
Craig Toppere058d272012-02-03 06:10:55 +0000115 NewFn = 0;
116 return true;
117 }
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000118 // SSE4.1 ptest functions may have an old signature.
119 if (Name.startswith("x86.sse41.ptest")) {
120 if (Name == "x86.sse41.ptestc")
121 return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestc, NewFn);
122 if (Name == "x86.sse41.ptestz")
123 return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestz, NewFn);
124 if (Name == "x86.sse41.ptestnzc")
125 return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestnzc, NewFn);
126 }
Craig Toppercc95b572012-06-13 07:18:53 +0000127 // frcz.ss/sd may need to have an argument dropped
128 if (Name.startswith("x86.xop.vfrcz.ss") && F->arg_size() == 2) {
129 F->setName(Name + ".old");
130 NewFn = Intrinsic::getDeclaration(F->getParent(),
131 Intrinsic::x86_xop_vfrcz_ss);
132 return true;
133 }
134 if (Name.startswith("x86.xop.vfrcz.sd") && F->arg_size() == 2) {
135 F->setName(Name + ".old");
136 NewFn = Intrinsic::getDeclaration(F->getParent(),
137 Intrinsic::x86_xop_vfrcz_sd);
138 return true;
139 }
Craig Topper7678de42012-06-03 08:07:25 +0000140 // Fix the FMA4 intrinsics to remove the 4
141 if (Name.startswith("x86.fma4.")) {
Craig Topperbb6e61c2012-06-03 16:48:52 +0000142 F->setName("llvm.x86.fma" + Name.substr(8));
143 NewFn = F;
144 return true;
Craig Topper7678de42012-06-03 08:07:25 +0000145 }
Craig Toppere058d272012-02-03 06:10:55 +0000146 break;
147 }
Chris Lattner747fddd2011-06-18 18:56:39 +0000148 }
Chandler Carruth69940402007-08-04 01:51:18 +0000149
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000150 // This may not belong here. This function is effectively being overloaded
151 // to both detect an intrinsic which needs upgrading, and to provide the
152 // upgraded form of the intrinsic. We should perhaps have two separate
Chandler Carruth69940402007-08-04 01:51:18 +0000153 // functions for this.
Evan Chengf9b83fc2007-12-17 22:33:23 +0000154 return false;
Chandler Carruth69940402007-08-04 01:51:18 +0000155}
156
Evan Chengf9b83fc2007-12-17 22:33:23 +0000157bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
158 NewFn = 0;
159 bool Upgraded = UpgradeIntrinsicFunction1(F, NewFn);
Duncan Sandsa3355ff2007-12-03 20:06:50 +0000160
161 // Upgrade intrinsic attributes. This does not change the function.
Evan Chengf9b83fc2007-12-17 22:33:23 +0000162 if (NewFn)
163 F = NewFn;
Dale Johannesen49de9822009-02-05 01:49:45 +0000164 if (unsigned id = F->getIntrinsicID())
Bill Wendlingcb3de0b2012-10-15 04:46:55 +0000165 F->setAttributes(Intrinsic::getAttributes(F->getContext(),
166 (Intrinsic::ID)id));
Duncan Sandsa3355ff2007-12-03 20:06:50 +0000167 return Upgraded;
168}
169
Bill Wendlingde49f362010-09-10 18:51:56 +0000170bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
Chris Lattnerb85e4eb2011-06-18 06:05:24 +0000171 // Nothing to do yet.
Bill Wendlingde49f362010-09-10 18:51:56 +0000172 return false;
173}
174
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000175// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the
176// upgraded intrinsic. All argument and return casting must be provided in
Chandler Carruth69940402007-08-04 01:51:18 +0000177// order to seamlessly integrate with existing context.
178void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Craig Toppere058d272012-02-03 06:10:55 +0000179 Function *F = CI->getCalledFunction();
Nick Lewyckybf47c762011-12-12 22:59:34 +0000180 LLVMContext &C = CI->getContext();
Chandler Carruthccbf1e32011-12-12 04:26:04 +0000181 IRBuilder<> Builder(C);
182 Builder.SetInsertPoint(CI->getParent(), CI);
183
Craig Toppere058d272012-02-03 06:10:55 +0000184 assert(F && "Intrinsic call is not direct?");
185
186 if (!NewFn) {
187 // Get the Function's name.
188 StringRef Name = F->getName();
189
190 Value *Rep;
191 // Upgrade packed integer vector compares intrinsics to compare instructions
192 if (Name.startswith("llvm.x86.sse2.pcmpeq.") ||
193 Name.startswith("llvm.x86.avx2.pcmpeq.")) {
194 Rep = Builder.CreateICmpEQ(CI->getArgOperand(0), CI->getArgOperand(1),
195 "pcmpeq");
196 // need to sign extend since icmp returns vector of i1
197 Rep = Builder.CreateSExt(Rep, CI->getType(), "");
198 } else if (Name.startswith("llvm.x86.sse2.pcmpgt.") ||
199 Name.startswith("llvm.x86.avx2.pcmpgt.")) {
200 Rep = Builder.CreateICmpSGT(CI->getArgOperand(0), CI->getArgOperand(1),
201 "pcmpgt");
202 // need to sign extend since icmp returns vector of i1
203 Rep = Builder.CreateSExt(Rep, CI->getType(), "");
Craig Topper189bce42012-05-08 06:58:15 +0000204 } else if (Name == "llvm.x86.avx.movnt.dq.256" ||
205 Name == "llvm.x86.avx.movnt.ps.256" ||
206 Name == "llvm.x86.avx.movnt.pd.256") {
207 IRBuilder<> Builder(C);
208 Builder.SetInsertPoint(CI->getParent(), CI);
209
210 Module *M = F->getParent();
211 SmallVector<Value *, 1> Elts;
212 Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1));
213 MDNode *Node = MDNode::get(C, Elts);
214
215 Value *Arg0 = CI->getArgOperand(0);
216 Value *Arg1 = CI->getArgOperand(1);
217
218 // Convert the type of the pointer to a pointer to the stored type.
219 Value *BC = Builder.CreateBitCast(Arg0,
220 PointerType::getUnqual(Arg1->getType()),
221 "cast");
222 StoreInst *SI = Builder.CreateStore(Arg1, BC);
223 SI->setMetadata(M->getMDKindID("nontemporal"), Node);
224 SI->setAlignment(16);
225
226 // Remove intrinsic.
227 CI->eraseFromParent();
228 return;
Craig Topperc29106b2012-06-09 16:46:13 +0000229 } else if (Name.startswith("llvm.x86.xop.vpcom")) {
230 Intrinsic::ID intID;
231 if (Name.endswith("ub"))
232 intID = Intrinsic::x86_xop_vpcomub;
233 else if (Name.endswith("uw"))
234 intID = Intrinsic::x86_xop_vpcomuw;
235 else if (Name.endswith("ud"))
236 intID = Intrinsic::x86_xop_vpcomud;
237 else if (Name.endswith("uq"))
238 intID = Intrinsic::x86_xop_vpcomuq;
239 else if (Name.endswith("b"))
240 intID = Intrinsic::x86_xop_vpcomb;
241 else if (Name.endswith("w"))
242 intID = Intrinsic::x86_xop_vpcomw;
243 else if (Name.endswith("d"))
244 intID = Intrinsic::x86_xop_vpcomd;
245 else if (Name.endswith("q"))
246 intID = Intrinsic::x86_xop_vpcomq;
247 else
248 llvm_unreachable("Unknown suffix");
249
250 Name = Name.substr(18); // strip off "llvm.x86.xop.vpcom"
251 unsigned Imm;
252 if (Name.startswith("lt"))
253 Imm = 0;
254 else if (Name.startswith("le"))
255 Imm = 1;
256 else if (Name.startswith("gt"))
257 Imm = 2;
258 else if (Name.startswith("ge"))
259 Imm = 3;
260 else if (Name.startswith("eq"))
261 Imm = 4;
262 else if (Name.startswith("ne"))
263 Imm = 5;
264 else if (Name.startswith("true"))
265 Imm = 6;
266 else if (Name.startswith("false"))
267 Imm = 7;
268 else
269 llvm_unreachable("Unknown condition");
270
271 Function *VPCOM = Intrinsic::getDeclaration(F->getParent(), intID);
272 Rep = Builder.CreateCall3(VPCOM, CI->getArgOperand(0),
273 CI->getArgOperand(1), Builder.getInt8(Imm));
Craig Toppere058d272012-02-03 06:10:55 +0000274 } else {
Craig Toppera963c812012-04-18 05:24:00 +0000275 bool PD128 = false, PD256 = false, PS128 = false, PS256 = false;
Craig Topper189bce42012-05-08 06:58:15 +0000276 if (Name == "llvm.x86.avx.vpermil.pd.256")
Craig Toppera963c812012-04-18 05:24:00 +0000277 PD256 = true;
Craig Topper189bce42012-05-08 06:58:15 +0000278 else if (Name == "llvm.x86.avx.vpermil.pd")
Craig Toppera963c812012-04-18 05:24:00 +0000279 PD128 = true;
Craig Topper189bce42012-05-08 06:58:15 +0000280 else if (Name == "llvm.x86.avx.vpermil.ps.256")
Craig Toppera963c812012-04-18 05:24:00 +0000281 PS256 = true;
Craig Topper189bce42012-05-08 06:58:15 +0000282 else if (Name == "llvm.x86.avx.vpermil.ps")
Craig Toppera963c812012-04-18 05:24:00 +0000283 PS128 = true;
284
285 if (PD256 || PD128 || PS256 || PS128) {
286 Value *Op0 = CI->getArgOperand(0);
287 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
288 SmallVector<Constant*, 8> Idxs;
289
290 if (PD128)
291 for (unsigned i = 0; i != 2; ++i)
292 Idxs.push_back(Builder.getInt32((Imm >> i) & 0x1));
293 else if (PD256)
294 for (unsigned l = 0; l != 4; l+=2)
295 for (unsigned i = 0; i != 2; ++i)
296 Idxs.push_back(Builder.getInt32(((Imm >> (l+i)) & 0x1) + l));
297 else if (PS128)
298 for (unsigned i = 0; i != 4; ++i)
299 Idxs.push_back(Builder.getInt32((Imm >> (2 * i)) & 0x3));
300 else if (PS256)
301 for (unsigned l = 0; l != 8; l+=4)
302 for (unsigned i = 0; i != 4; ++i)
303 Idxs.push_back(Builder.getInt32(((Imm >> (2 * i)) & 0x3) + l));
304 else
305 llvm_unreachable("Unexpected function");
306
307 Rep = Builder.CreateShuffleVector(Op0, Op0, ConstantVector::get(Idxs));
308 } else {
309 llvm_unreachable("Unknown function for CallInst upgrade.");
310 }
Craig Toppere058d272012-02-03 06:10:55 +0000311 }
312
313 CI->replaceAllUsesWith(Rep);
314 CI->eraseFromParent();
315 return;
316 }
317
Chandler Carruth7325f062012-07-20 21:09:18 +0000318 std::string Name = CI->getName().str();
319 CI->setName(Name + ".old");
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000320
Chandler Carruthccbf1e32011-12-12 04:26:04 +0000321 switch (NewFn->getIntrinsicID()) {
322 default:
Chris Lattnerb5dd9de2011-11-27 08:42:07 +0000323 llvm_unreachable("Unknown function for CallInst upgrade.");
Chandler Carruthccbf1e32011-12-12 04:26:04 +0000324
325 case Intrinsic::ctlz:
Nuno Lopes23e75da2012-05-22 15:25:31 +0000326 case Intrinsic::cttz:
Chandler Carruthccbf1e32011-12-12 04:26:04 +0000327 assert(CI->getNumArgOperands() == 1 &&
328 "Mismatch between function args and call args");
Chandler Carruthccbf1e32011-12-12 04:26:04 +0000329 CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0),
330 Builder.getFalse(), Name));
331 CI->eraseFromParent();
332 return;
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000333
Matt Arsenaultc4a8c072013-10-07 18:06:48 +0000334 case Intrinsic::objectsize:
335 CI->replaceAllUsesWith(Builder.CreateCall2(NewFn,
336 CI->getArgOperand(0),
337 CI->getArgOperand(1),
338 Name));
339 CI->eraseFromParent();
340 return;
341
Joel Jones06a6a302012-07-13 23:25:25 +0000342 case Intrinsic::arm_neon_vclz: {
343 // Change name from llvm.arm.neon.vclz.* to llvm.ctlz.*
344 CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0),
Joel Jones7c82e6a2012-07-18 00:02:16 +0000345 Builder.getFalse(),
Joel Jones06a6a302012-07-13 23:25:25 +0000346 "llvm.ctlz." + Name.substr(14)));
347 CI->eraseFromParent();
348 return;
349 }
Joel Jones7c82e6a2012-07-18 00:02:16 +0000350 case Intrinsic::ctpop: {
351 CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0)));
352 CI->eraseFromParent();
353 return;
354 }
Joel Jones06a6a302012-07-13 23:25:25 +0000355
Craig Toppercc95b572012-06-13 07:18:53 +0000356 case Intrinsic::x86_xop_vfrcz_ss:
357 case Intrinsic::x86_xop_vfrcz_sd:
358 CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(1),
359 Name));
360 CI->eraseFromParent();
361 return;
362
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000363 case Intrinsic::x86_sse41_ptestc:
364 case Intrinsic::x86_sse41_ptestz:
Craig Toppercc95b572012-06-13 07:18:53 +0000365 case Intrinsic::x86_sse41_ptestnzc: {
Nadav Rotem3c98ce22012-06-10 18:42:51 +0000366 // The arguments for these intrinsics used to be v4f32, and changed
367 // to v2i64. This is purely a nop, since those are bitwise intrinsics.
368 // So, the only thing required is a bitcast for both arguments.
369 // First, check the arguments have the old type.
370 Value *Arg0 = CI->getArgOperand(0);
371 if (Arg0->getType() != VectorType::get(Type::getFloatTy(C), 4))
372 return;
373
374 // Old intrinsic, add bitcasts
375 Value *Arg1 = CI->getArgOperand(1);
376
377 Value *BC0 =
378 Builder.CreateBitCast(Arg0,
379 VectorType::get(Type::getInt64Ty(C), 2),
380 "cast");
381 Value *BC1 =
382 Builder.CreateBitCast(Arg1,
383 VectorType::get(Type::getInt64Ty(C), 2),
384 "cast");
385
386 CallInst* NewCall = Builder.CreateCall2(NewFn, BC0, BC1, Name);
387 CI->replaceAllUsesWith(NewCall);
388 CI->eraseFromParent();
389 return;
Evan Chengf9b83fc2007-12-17 22:33:23 +0000390 }
Craig Toppercc95b572012-06-13 07:18:53 +0000391 }
Chandler Carruth69940402007-08-04 01:51:18 +0000392}
393
Matt Arsenault3f493222013-07-20 17:46:00 +0000394// This tests each Function to determine if it needs upgrading. When we find
395// one we are interested in, we then upgrade all calls to reflect the new
Chandler Carruth69940402007-08-04 01:51:18 +0000396// function.
397void llvm::UpgradeCallsToIntrinsic(Function* F) {
398 assert(F && "Illegal attempt to upgrade a non-existent intrinsic.");
399
400 // Upgrade the function and check if it is a totaly new function.
Chris Lattnerb85e4eb2011-06-18 06:05:24 +0000401 Function *NewFn;
Evan Chengf9b83fc2007-12-17 22:33:23 +0000402 if (UpgradeIntrinsicFunction(F, NewFn)) {
Chandler Carruth69940402007-08-04 01:51:18 +0000403 if (NewFn != F) {
404 // Replace all uses to the old function with the new one if necessary.
405 for (Value::use_iterator UI = F->use_begin(), UE = F->use_end();
406 UI != UE; ) {
Chris Lattnerb85e4eb2011-06-18 06:05:24 +0000407 if (CallInst *CI = dyn_cast<CallInst>(*UI++))
Chandler Carruth69940402007-08-04 01:51:18 +0000408 UpgradeIntrinsicCall(CI, NewFn);
409 }
410 // Remove old function, no longer used, from the module.
411 F->eraseFromParent();
412 }
413 }
414}
Devang Patele4b27562009-08-28 23:24:31 +0000415
Manman Ren804f0342013-09-28 00:22:27 +0000416void llvm::UpgradeInstWithTBAATag(Instruction *I) {
417 MDNode *MD = I->getMetadata(LLVMContext::MD_tbaa);
418 assert(MD && "UpgradeInstWithTBAATag should have a TBAA tag");
419 // Check if the tag uses struct-path aware TBAA format.
420 if (isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3)
421 return;
422
423 if (MD->getNumOperands() == 3) {
424 Value *Elts[] = {
425 MD->getOperand(0),
426 MD->getOperand(1)
427 };
428 MDNode *ScalarType = MDNode::get(I->getContext(), Elts);
429 // Create a MDNode <ScalarType, ScalarType, offset 0, const>
430 Value *Elts2[] = {
431 ScalarType, ScalarType,
432 Constant::getNullValue(Type::getInt64Ty(I->getContext())),
433 MD->getOperand(2)
434 };
435 I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts2));
436 } else {
437 // Create a MDNode <MD, MD, offset 0>
438 Value *Elts[] = {MD, MD,
439 Constant::getNullValue(Type::getInt64Ty(I->getContext()))};
440 I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts));
441 }
442}