Skip to content

Commit 36f0d64

Browse files
authored
[SandboxIR] Implement AllocaInst (#102027)
This patch implements sandboxir::AllocaInst which mirrors llvm::AllocaInst.
1 parent a3ccaed commit 36f0d64

File tree

7 files changed

+453
-1
lines changed

7 files changed

+453
-1
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class GetElementPtrInst;
124124
class CastInst;
125125
class PtrToIntInst;
126126
class BitCastInst;
127+
class AllocaInst;
127128

128129
/// Iterator for the `Use` edges of a User's operands.
129130
/// \Returns the operand `Use` when dereferenced.
@@ -240,6 +241,7 @@ class Value {
240241
friend class InvokeInst; // For getting `Val`.
241242
friend class CallBrInst; // For getting `Val`.
242243
friend class GetElementPtrInst; // For getting `Val`.
244+
friend class AllocaInst; // For getting `Val`.
243245
friend class CastInst; // For getting `Val`.
244246
friend class PHINode; // For getting `Val`.
245247

@@ -633,6 +635,7 @@ class Instruction : public sandboxir::User {
633635
friend class InvokeInst; // For getTopmostLLVMInstruction().
634636
friend class CallBrInst; // For getTopmostLLVMInstruction().
635637
friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
638+
friend class AllocaInst; // For getTopmostLLVMInstruction().
636639
friend class CastInst; // For getTopmostLLVMInstruction().
637640
friend class PHINode; // For getTopmostLLVMInstruction().
638641

@@ -1393,6 +1396,103 @@ class GetElementPtrInst final : public Instruction {
13931396
#endif
13941397
};
13951398

1399+
class AllocaInst final : public UnaryInstruction {
1400+
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
1401+
return getOperandUseDefault(OpIdx, Verify);
1402+
}
1403+
SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
1404+
return {cast<llvm::Instruction>(Val)};
1405+
}
1406+
1407+
AllocaInst(llvm::AllocaInst *AI, Context &Ctx)
1408+
: UnaryInstruction(ClassID::Alloca, Instruction::Opcode::Alloca, AI,
1409+
Ctx) {}
1410+
friend class Context; // For constructor.
1411+
1412+
public:
1413+
static AllocaInst *create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
1414+
BasicBlock *WhereBB, Context &Ctx,
1415+
Value *ArraySize = nullptr, const Twine &Name = "");
1416+
static AllocaInst *create(Type *Ty, unsigned AddrSpace,
1417+
Instruction *InsertBefore, Context &Ctx,
1418+
Value *ArraySize = nullptr, const Twine &Name = "");
1419+
static AllocaInst *create(Type *Ty, unsigned AddrSpace,
1420+
BasicBlock *InsertAtEnd, Context &Ctx,
1421+
Value *ArraySize = nullptr, const Twine &Name = "");
1422+
1423+
unsigned getUseOperandNo(const Use &Use) const final {
1424+
return getUseOperandNoDefault(Use);
1425+
}
1426+
unsigned getNumOfIRInstrs() const final { return 1u; }
1427+
1428+
/// Return true if there is an allocation size parameter to the allocation
1429+
/// instruction that is not 1.
1430+
bool isArrayAllocation() const {
1431+
return cast<llvm::AllocaInst>(Val)->isArrayAllocation();
1432+
}
1433+
/// Get the number of elements allocated. For a simple allocation of a single
1434+
/// element, this will return a constant 1 value.
1435+
Value *getArraySize();
1436+
const Value *getArraySize() const {
1437+
return const_cast<AllocaInst *>(this)->getArraySize();
1438+
}
1439+
/// Overload to return most specific pointer type.
1440+
PointerType *getType() const {
1441+
return cast<llvm::AllocaInst>(Val)->getType();
1442+
}
1443+
/// Return the address space for the allocation.
1444+
unsigned getAddressSpace() const {
1445+
return cast<llvm::AllocaInst>(Val)->getAddressSpace();
1446+
}
1447+
/// Get allocation size in bytes. Returns std::nullopt if size can't be
1448+
/// determined, e.g. in case of a VLA.
1449+
std::optional<TypeSize> getAllocationSize(const DataLayout &DL) const {
1450+
return cast<llvm::AllocaInst>(Val)->getAllocationSize(DL);
1451+
}
1452+
/// Get allocation size in bits. Returns std::nullopt if size can't be
1453+
/// determined, e.g. in case of a VLA.
1454+
std::optional<TypeSize> getAllocationSizeInBits(const DataLayout &DL) const {
1455+
return cast<llvm::AllocaInst>(Val)->getAllocationSizeInBits(DL);
1456+
}
1457+
/// Return the type that is being allocated by the instruction.
1458+
Type *getAllocatedType() const {
1459+
return cast<llvm::AllocaInst>(Val)->getAllocatedType();
1460+
}
1461+
/// for use only in special circumstances that need to generically
1462+
/// transform a whole instruction (eg: IR linking and vectorization).
1463+
void setAllocatedType(Type *Ty);
1464+
/// Return the alignment of the memory that is being allocated by the
1465+
/// instruction.
1466+
Align getAlign() const { return cast<llvm::AllocaInst>(Val)->getAlign(); }
1467+
void setAlignment(Align Align);
1468+
/// Return true if this alloca is in the entry block of the function and is a
1469+
/// constant size. If so, the code generator will fold it into the
1470+
/// prolog/epilog code, so it is basically free.
1471+
bool isStaticAlloca() const {
1472+
return cast<llvm::AllocaInst>(Val)->isStaticAlloca();
1473+
}
1474+
/// Return true if this alloca is used as an inalloca argument to a call. Such
1475+
/// allocas are never considered static even if they are in the entry block.
1476+
bool isUsedWithInAlloca() const {
1477+
return cast<llvm::AllocaInst>(Val)->isUsedWithInAlloca();
1478+
}
1479+
/// Specify whether this alloca is used to represent the arguments to a call.
1480+
void setUsedWithInAlloca(bool V);
1481+
1482+
static bool classof(const Value *From) {
1483+
if (auto *I = dyn_cast<Instruction>(From))
1484+
return I->getSubclassID() == Instruction::ClassID::Alloca;
1485+
return false;
1486+
}
1487+
#ifndef NDEBUG
1488+
void verify() const final {
1489+
assert(isa<llvm::AllocaInst>(Val) && "Expected AllocaInst!");
1490+
}
1491+
void dump(raw_ostream &OS) const override;
1492+
LLVM_DUMP_METHOD void dump() const override;
1493+
#endif
1494+
};
1495+
13961496
class CastInst : public UnaryInstruction {
13971497
static Opcode getCastOpcode(llvm::Instruction::CastOps CastOp) {
13981498
switch (CastOp) {
@@ -1726,6 +1826,8 @@ class Context {
17261826
friend CallBrInst; // For createCallBrInst()
17271827
GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I);
17281828
friend GetElementPtrInst; // For createGetElementPtrInst()
1829+
AllocaInst *createAllocaInst(llvm::AllocaInst *I);
1830+
friend AllocaInst; // For createAllocaInst()
17291831
CastInst *createCastInst(llvm::CastInst *I);
17301832
friend CastInst; // For createCastInst()
17311833
PHINode *createPHINode(llvm::PHINode *I);

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ DEF_INSTR(Call, OP(Call), CallInst)
4343
DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
4444
DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
4545
DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
46+
DEF_INSTR(Alloca, OP(Alloca), AllocaInst)
4647
DEF_INSTR(Cast, OPCODES(\
4748
OP(ZExt) \
4849
OP(SExt) \

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class LoadInst;
5858
class StoreInst;
5959
class Instruction;
6060
class Tracker;
61+
class AllocaInst;
6162

6263
/// The base class for IR Change classes.
6364
class IRChangeBase {
@@ -255,6 +256,57 @@ class CallBrInstSetDefaultDest : public IRChangeBase {
255256
#endif
256257
};
257258

259+
class AllocaSetAllocatedType final : public IRChangeBase {
260+
AllocaInst *Alloca;
261+
Type *OrigType;
262+
263+
public:
264+
AllocaSetAllocatedType(AllocaInst *Alloca, Tracker &Tracker);
265+
void revert() final;
266+
void accept() final {}
267+
#ifndef NDEBUG
268+
void dump(raw_ostream &OS) const final {
269+
dumpCommon(OS);
270+
OS << "AllocaSetAllocatedType";
271+
}
272+
LLVM_DUMP_METHOD void dump() const final;
273+
#endif
274+
};
275+
276+
class AllocaSetAlignment final : public IRChangeBase {
277+
AllocaInst *Alloca;
278+
Align OrigAlign;
279+
280+
public:
281+
AllocaSetAlignment(AllocaInst *Alloca, Tracker &Tracker);
282+
void revert() final;
283+
void accept() final {}
284+
#ifndef NDEBUG
285+
void dump(raw_ostream &OS) const final {
286+
dumpCommon(OS);
287+
OS << "AllocaSetAlignment";
288+
}
289+
LLVM_DUMP_METHOD void dump() const final;
290+
#endif
291+
};
292+
293+
class AllocaSetUsedWithInAlloca final : public IRChangeBase {
294+
AllocaInst *Alloca;
295+
bool Orig;
296+
297+
public:
298+
AllocaSetUsedWithInAlloca(AllocaInst *Alloca, Tracker &Tracker);
299+
void revert() final;
300+
void accept() final {}
301+
#ifndef NDEBUG
302+
void dump(raw_ostream &OS) const final {
303+
dumpCommon(OS);
304+
OS << "AllocaSetUsedWithInAlloca";
305+
}
306+
LLVM_DUMP_METHOD void dump() const final;
307+
#endif
308+
};
309+
258310
class CallBrInstSetIndirectDest : public IRChangeBase {
259311
CallBrInst *CallBr;
260312
unsigned Idx;

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,69 @@ static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {
12321232
}
12331233
}
12341234

1235+
AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
1236+
BasicBlock *WhereBB, Context &Ctx,
1237+
Value *ArraySize, const Twine &Name) {
1238+
auto &Builder = Ctx.getLLVMIRBuilder();
1239+
if (WhereIt == WhereBB->end())
1240+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
1241+
else
1242+
Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
1243+
auto *NewAlloca = Builder.CreateAlloca(Ty, AddrSpace, ArraySize->Val, Name);
1244+
return Ctx.createAllocaInst(NewAlloca);
1245+
}
1246+
1247+
AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
1248+
Instruction *InsertBefore, Context &Ctx,
1249+
Value *ArraySize, const Twine &Name) {
1250+
return create(Ty, AddrSpace, InsertBefore->getIterator(),
1251+
InsertBefore->getParent(), Ctx, ArraySize, Name);
1252+
}
1253+
1254+
AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
1255+
BasicBlock *InsertAtEnd, Context &Ctx,
1256+
Value *ArraySize, const Twine &Name) {
1257+
return create(Ty, AddrSpace, InsertAtEnd->end(), InsertAtEnd, Ctx, ArraySize,
1258+
Name);
1259+
}
1260+
1261+
void AllocaInst::setAllocatedType(Type *Ty) {
1262+
auto &Tracker = Ctx.getTracker();
1263+
if (Tracker.isTracking())
1264+
Tracker.track(std::make_unique<AllocaSetAllocatedType>(this, Tracker));
1265+
cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty);
1266+
}
1267+
1268+
void AllocaInst::setAlignment(Align Align) {
1269+
auto &Tracker = Ctx.getTracker();
1270+
if (Tracker.isTracking())
1271+
Tracker.track(std::make_unique<AllocaSetAlignment>(this, Tracker));
1272+
cast<llvm::AllocaInst>(Val)->setAlignment(Align);
1273+
}
1274+
1275+
void AllocaInst::setUsedWithInAlloca(bool V) {
1276+
auto &Tracker = Ctx.getTracker();
1277+
if (Tracker.isTracking())
1278+
Tracker.track(std::make_unique<AllocaSetUsedWithInAlloca>(this, Tracker));
1279+
cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
1280+
}
1281+
1282+
Value *AllocaInst::getArraySize() {
1283+
return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());
1284+
}
1285+
1286+
#ifndef NDEBUG
1287+
void AllocaInst::dump(raw_ostream &OS) const {
1288+
dumpCommonPrefix(OS);
1289+
dumpCommonSuffix(OS);
1290+
}
1291+
1292+
void AllocaInst::dump() const {
1293+
dump(dbgs());
1294+
dbgs() << "\n";
1295+
}
1296+
#endif // NDEBUG
1297+
12351298
Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
12361299
BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
12371300
const Twine &Name) {
@@ -1472,6 +1535,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
14721535
new GetElementPtrInst(LLVMGEP, *this));
14731536
return It->second.get();
14741537
}
1538+
case llvm::Instruction::Alloca: {
1539+
auto *LLVMAlloca = cast<llvm::AllocaInst>(LLVMV);
1540+
It->second = std::unique_ptr<AllocaInst>(new AllocaInst(LLVMAlloca, *this));
1541+
return It->second.get();
1542+
}
14751543
case llvm::Instruction::ZExt:
14761544
case llvm::Instruction::SExt:
14771545
case llvm::Instruction::FPToUI:
@@ -1558,7 +1626,10 @@ Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
15581626
std::unique_ptr<GetElementPtrInst>(new GetElementPtrInst(I, *this));
15591627
return cast<GetElementPtrInst>(registerValue(std::move(NewPtr)));
15601628
}
1561-
1629+
AllocaInst *Context::createAllocaInst(llvm::AllocaInst *I) {
1630+
auto NewPtr = std::unique_ptr<AllocaInst>(new AllocaInst(I, *this));
1631+
return cast<AllocaInst>(registerValue(std::move(NewPtr)));
1632+
}
15621633
CastInst *Context::createCastInst(llvm::CastInst *I) {
15631634
auto NewPtr = std::unique_ptr<CastInst>(new CastInst(I, *this));
15641635
return cast<CastInst>(registerValue(std::move(NewPtr)));

llvm/lib/SandboxIR/Tracker.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,46 @@ void RemoveFromParent::dump() const {
204204
}
205205
#endif
206206

207+
AllocaSetAllocatedType::AllocaSetAllocatedType(AllocaInst *Alloca,
208+
Tracker &Tracker)
209+
: IRChangeBase(Tracker), Alloca(Alloca),
210+
OrigType(Alloca->getAllocatedType()) {}
211+
212+
void AllocaSetAllocatedType::revert() { Alloca->setAllocatedType(OrigType); }
213+
214+
#ifndef NDEBUG
215+
void AllocaSetAllocatedType::dump() const {
216+
dump(dbgs());
217+
dbgs() << "\n";
218+
}
219+
#endif // NDEBUG
220+
221+
AllocaSetAlignment::AllocaSetAlignment(AllocaInst *Alloca, Tracker &Tracker)
222+
: IRChangeBase(Tracker), Alloca(Alloca), OrigAlign(Alloca->getAlign()) {}
223+
224+
void AllocaSetAlignment::revert() { Alloca->setAlignment(OrigAlign); }
225+
226+
#ifndef NDEBUG
227+
void AllocaSetAlignment::dump() const {
228+
dump(dbgs());
229+
dbgs() << "\n";
230+
}
231+
#endif // NDEBUG
232+
233+
AllocaSetUsedWithInAlloca::AllocaSetUsedWithInAlloca(AllocaInst *Alloca,
234+
Tracker &Tracker)
235+
: IRChangeBase(Tracker), Alloca(Alloca),
236+
Orig(Alloca->isUsedWithInAlloca()) {}
237+
238+
void AllocaSetUsedWithInAlloca::revert() { Alloca->setUsedWithInAlloca(Orig); }
239+
240+
#ifndef NDEBUG
241+
void AllocaSetUsedWithInAlloca::dump() const {
242+
dump(dbgs());
243+
dbgs() << "\n";
244+
}
245+
#endif // NDEBUG
246+
207247
CallBrInstSetDefaultDest::CallBrInstSetDefaultDest(CallBrInst *CallBr,
208248
Tracker &Tracker)
209249
: IRChangeBase(Tracker), CallBr(CallBr) {

0 commit comments

Comments
 (0)