diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 3a59e58b018..61d0efafe5f 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -211,9 +211,11 @@ public: /// SubclassData field in Value to store whether or not the load is volatile. /// class LoadInst : public UnaryInstruction { + LoadInst(const LoadInst &LI) : UnaryInstruction(LI.getType(), Load, LI.getOperand(0)) { setVolatile(LI.isVolatile()); + setAlignment(LI.getAlignment()); #ifndef NDEBUG AssertOK(); @@ -223,14 +225,16 @@ class LoadInst : public UnaryInstruction { public: LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBefore); LoadInst(Value *Ptr, const std::string &Name, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const std::string &Name, bool isVolatile = false, + LoadInst(Value *Ptr, const std::string &Name, bool isVolatile = false, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, unsigned Align, Instruction *InsertBefore = 0); LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, BasicBlock *InsertAtEnd); LoadInst(Value *Ptr, const char *Name, Instruction *InsertBefore); LoadInst(Value *Ptr, const char *Name, BasicBlock *InsertAtEnd); - explicit LoadInst(Value *Ptr, const char *Name = 0, bool isVolatile = false, + explicit LoadInst(Value *Ptr, const char *Name = 0, bool isVolatile = false, Instruction *InsertBefore = 0); LoadInst(Value *Ptr, const char *Name, bool isVolatile, BasicBlock *InsertAtEnd); @@ -238,14 +242,25 @@ public: /// isVolatile - Return true if this is a load from a volatile memory /// location. /// - bool isVolatile() const { return SubclassData; } + bool isVolatile() const { return SubclassData & 1; } /// setVolatile - Specify whether this is a volatile load or not. /// - void setVolatile(bool V) { SubclassData = V; } + void setVolatile(bool V) { + SubclassData = (SubclassData & ~1) | ((V) ? 1 : 0); + } virtual LoadInst *clone() const; + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + signed Log2AlignVal = ((SubclassData>>1)-1); + return ((Log2AlignVal < 0) ? 0 : 1<>1)-1); + return ((Log2AlignVal < 0) ? 0 : 1<getDescription()); if (!isa($3->get())) @@ -2951,10 +2951,10 @@ MemoryInst : MALLOC Types OptCAlign { (*$3)->getDescription()); Value* tmpVal = getVal(*$3, $4); CHECK_FOR_ERROR - $$ = new LoadInst(tmpVal, "", $1); + $$ = new LoadInst(tmpVal, "", $1, $5); delete $3; } - | OptVolatile STORE ResolvedVal ',' Types ValueRef { + | OptVolatile STORE ResolvedVal ',' Types ValueRef OptCAlign { if (!UpRefs.empty()) GEN_ERROR("Invalid upreference in type: " + (*$5)->getDescription()); const PointerType *PT = dyn_cast($5->get()); @@ -2968,7 +2968,7 @@ MemoryInst : MALLOC Types OptCAlign { Value* tmpVal = getVal(*$5, $6); CHECK_FOR_ERROR - $$ = new StoreInst($3, tmpVal, $1); + $$ = new StoreInst($3, tmpVal, $1, $7); delete $5; } | GETELEMENTPTR Types ValueRef IndexList { diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 4cb67c31565..7ac784ecc7c 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -831,13 +831,31 @@ void BytecodeReader::ParseInstruction(SmallVector &Oprnds, &Idx[0], Idx.size()); break; } - case 62: // volatile load + case 62: { // attributed load + if (Oprnds.size() != 2 || !isa(InstTy)) + error("Invalid attributed load instruction!"); + signed Log2AlignVal = ((Oprnds[1]>>1)-1); + Result = new LoadInst(getValue(iType, Oprnds[0]), "", (Oprnds[1] & 1), + ((Log2AlignVal < 0) ? 0 : 1<(InstTy)) error("Invalid load instruction!"); - Result = new LoadInst(getValue(iType, Oprnds[0]), "", Opcode == 62); + Result = new LoadInst(getValue(iType, Oprnds[0]), ""); break; - case 63: // volatile store + case 63: { // attributed store + if (!isa(InstTy) || Oprnds.size() != 3) + error("Invalid attributed store instruction!"); + + Value *Ptr = getValue(iType, Oprnds[1]); + const Type *ValTy = cast(Ptr->getType())->getElementType(); + signed Log2AlignVal = ((Oprnds[2]>>1)-1); + Result = new StoreInst(getValue(getTypeSlot(ValTy), Oprnds[0]), Ptr, + (Oprnds[2] & 1), + ((Log2AlignVal < 0) ? 0 : 1<(InstTy) || Oprnds.size() != 2) error("Invalid store instruction!"); diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index 4688e69ef2f..12724dd6bec 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -445,7 +445,8 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, unsigned NumArgs = I->getNumOperands(); bool HasExtraArg = false; if (isa(I) || isa(I) || - isa(I) || isa(I) || Opcode == 58) + isa(I) || isa(I) || Opcode == 58 || + Opcode == 62 || Opcode == 63) HasExtraArg = true; if (const AllocationInst *AI = dyn_cast(I)) HasExtraArg = AI->getAlignment() != 0; @@ -468,6 +469,12 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, } else if (const AllocationInst *AI = dyn_cast(I)) { if (AI->getAlignment()) output_vbr((unsigned)Log2_32(AI->getAlignment())+1); + } else if (Opcode == 62) { // Attributed load + output_vbr((unsigned)(((Log2_32(cast(I)->getAlignment())+1)<<1) + + (cast(I)->isVolatile() ? 1 : 0))); + } else if (Opcode == 63) { // Attributed store + output_vbr((unsigned)(((Log2_32(cast(I)->getAlignment())+1)<<1) + + (cast(I)->isVolatile() ? 1 : 0))); } } else { output_vbr(Table.getSlot(I->getOperand(0))); @@ -616,7 +623,7 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { unsigned Opcode = I.getOpcode(); unsigned NumOperands = I.getNumOperands(); - // Encode 'tail call' as 61, 'volatile load' as 62, and 'volatile store' as + // Encode 'tail call' as 61 // 63. if (const CallInst *CI = dyn_cast(&I)) { if (CI->getCallingConv() == CallingConv::C) { @@ -632,10 +639,6 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { } else { Opcode = 58; // Call escape sequence. } - } else if (isa(I) && cast(I).isVolatile()) { - Opcode = 62; - } else if (isa(I) && cast(I).isVolatile()) { - Opcode = 63; } // Figure out which type to encode with the instruction. Typically we want @@ -744,6 +747,32 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { } else if (isa(I)) { // Invoke escape seq has at least 4 operands to encode. ++NumOperands; + } else if (const LoadInst *LI = dyn_cast(&I)) { + // Encode attributed load as opcode 62 + // We need to encode the attributes of the load instruction as the second + // operand. Its not really a slot, but we don't want to break the + // instruction format for these instructions. + if (LI->getAlignment() || LI->isVolatile()) { + NumOperands = 2; + Slots[1] = ((Log2_32(LI->getAlignment())+1)<<1) + + (LI->isVolatile() ? 1 : 0); + if (Slots[1] > MaxOpSlot) + MaxOpSlot = Slots[1]; + Opcode = 62; + } + } else if (const StoreInst *SI = dyn_cast(&I)) { + // Encode attributed store as opcode 63 + // We need to encode the attributes of the store instruction as the third + // operand. Its not really a slot, but we don't want to break the + // instruction format for these instructions. + if (SI->getAlignment() || SI->isVolatile()) { + NumOperands = 3; + Slots[2] = ((Log2_32(SI->getAlignment())+1)<<1) + + (SI->isVolatile() ? 1 : 0); + if (Slots[2] > MaxOpSlot) + MaxOpSlot = Slots[2]; + Opcode = 63; + } } // Decide which instruction encoding to use. This is determined primarily diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 63ec8e423e5..90f0198b570 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1307,6 +1307,13 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(i), PrintAllTypes); } } + + // Print post operand alignment for load/store + if (isa(I) && cast(I).getAlignment()) { + Out << ", align " << cast(I).getAlignment(); + } else if (isa(I) && cast(I).getAlignment()) { + Out << ", align " << cast(I).getAlignment(); + } printInfoComment(I); Out << "\n"; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index e0c2a5e6bb6..2bd350080e3 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -20,6 +20,7 @@ #include "llvm/ParameterAttributes.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/ConstantRange.h" +#include "llvm/Support/MathExtras.h" using namespace llvm; unsigned CallSite::getCallingConv() const { @@ -705,6 +706,7 @@ LoadInst::LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBef) : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertBef) { setVolatile(false); + setAlignment(0); AssertOK(); setName(Name); } @@ -713,6 +715,7 @@ LoadInst::LoadInst(Value *Ptr, const std::string &Name, BasicBlock *InsertAE) : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertAE) { setVolatile(false); + setAlignment(0); AssertOK(); setName(Name); } @@ -722,6 +725,17 @@ LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertBef) { setVolatile(isVolatile); + setAlignment(0); + AssertOK(); + setName(Name); +} + +LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, + unsigned Align, Instruction *InsertBef) + : UnaryInstruction(cast(Ptr->getType())->getElementType(), + Load, Ptr, InsertBef) { + setVolatile(isVolatile); + setAlignment(Align); AssertOK(); setName(Name); } @@ -731,6 +745,7 @@ LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertAE) { setVolatile(isVolatile); + setAlignment(0); AssertOK(); setName(Name); } @@ -741,6 +756,7 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, Instruction *InsertBef) : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertBef) { setVolatile(false); + setAlignment(0); AssertOK(); if (Name && Name[0]) setName(Name); } @@ -749,6 +765,7 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, BasicBlock *InsertAE) : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertAE) { setVolatile(false); + setAlignment(0); AssertOK(); if (Name && Name[0]) setName(Name); } @@ -758,6 +775,7 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile, : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertBef) { setVolatile(isVolatile); + setAlignment(0); AssertOK(); if (Name && Name[0]) setName(Name); } @@ -767,10 +785,15 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile, : UnaryInstruction(cast(Ptr->getType())->getElementType(), Load, Ptr, InsertAE) { setVolatile(isVolatile); + setAlignment(0); AssertOK(); if (Name && Name[0]) setName(Name); } +void LoadInst::setAlignment(unsigned Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + SubclassData = (SubclassData & 1) | ((Log2_32(Align)+1)<<1); +} //===----------------------------------------------------------------------===// // StoreInst Implementation @@ -790,6 +813,7 @@ StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore) Ops[0].init(val, this); Ops[1].init(addr, this); setVolatile(false); + setAlignment(0); AssertOK(); } @@ -798,6 +822,7 @@ StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd) Ops[0].init(val, this); Ops[1].init(addr, this); setVolatile(false); + setAlignment(0); AssertOK(); } @@ -807,6 +832,17 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, Ops[0].init(val, this); Ops[1].init(addr, this); setVolatile(isVolatile); + setAlignment(0); + AssertOK(); +} + +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, + unsigned Align, Instruction *InsertBefore) + : Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) { + Ops[0].init(val, this); + Ops[1].init(addr, this); + setVolatile(isVolatile); + setAlignment(Align); AssertOK(); } @@ -816,9 +852,15 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, Ops[0].init(val, this); Ops[1].init(addr, this); setVolatile(isVolatile); + setAlignment(0); AssertOK(); } +void StoreInst::setAlignment(unsigned Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + SubclassData = (SubclassData & 1) | ((Log2_32(Align)+1)<<1); +} + //===----------------------------------------------------------------------===// // GetElementPtrInst Implementation //===----------------------------------------------------------------------===//