summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Instructions.h44
-rw-r--r--lib/AsmParser/llvmAsmParser.y8
-rw-r--r--lib/Bytecode/Reader/Reader.cpp24
-rw-r--r--lib/Bytecode/Writer/Writer.cpp41
-rw-r--r--lib/VMCore/AsmWriter.cpp7
-rw-r--r--lib/VMCore/Instructions.cpp42
6 files changed, 146 insertions, 20 deletions
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<<Log2AlignVal);
+ }
+
+ void setAlignment(unsigned Align);
+
Value *getPointerOperand() { return getOperand(0); }
const Value *getPointerOperand() const { return getOperand(0); }
static unsigned getPointerOperandIndex() { return 0U; }
@@ -269,10 +284,13 @@ public:
///
class StoreInst : public Instruction {
Use Ops[2];
+
StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, Ops, 2) {
Ops[0].init(SI.Ops[0], this);
Ops[1].init(SI.Ops[1], this);
setVolatile(SI.isVolatile());
+ setAlignment(SI.getAlignment());
+
#ifndef NDEBUG
AssertOK();
#endif
@@ -283,17 +301,21 @@ public:
StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd);
StoreInst(Value *Val, Value *Ptr, bool isVolatile = false,
Instruction *InsertBefore = 0);
+ StoreInst(Value *Val, Value *Ptr, bool isVolatile,
+ unsigned Align, Instruction *InsertBefore = 0);
StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd);
/// 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);
+ }
/// Transparently provide more efficient getOperand methods.
Value *getOperand(unsigned i) const {
@@ -306,7 +328,15 @@ public:
}
unsigned getNumOperands() const { return 2; }
-
+ /// getAlignment - Return the alignment of the access that is being performed
+ ///
+ unsigned getAlignment() const {
+ signed Log2AlignVal = ((SubclassData>>1)-1);
+ return ((Log2AlignVal < 0) ? 0 : 1<<Log2AlignVal);
+ }
+
+ void setAlignment(unsigned Align);
+
virtual StoreInst *clone() const;
Value *getPointerOperand() { return getOperand(1); }
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 9b5cc5abfd5..2b08d3afa1b 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -2940,7 +2940,7 @@ MemoryInst : MALLOC Types OptCAlign {
CHECK_FOR_ERROR
}
- | OptVolatile LOAD Types ValueRef {
+ | OptVolatile LOAD Types ValueRef OptCAlign {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
if (!isa<PointerType>($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<PointerType>($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<unsigned, 8> &Oprnds,
&Idx[0], Idx.size());
break;
}
- case 62: // volatile load
+ case 62: { // attributed load
+ if (Oprnds.size() != 2 || !isa<PointerType>(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<<Log2AlignVal));
+ break;
+ }
case Instruction::Load:
if (Oprnds.size() != 1 || !isa<PointerType>(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<PointerType>(InstTy) || Oprnds.size() != 3)
+ error("Invalid attributed store instruction!");
+
+ Value *Ptr = getValue(iType, Oprnds[1]);
+ const Type *ValTy = cast<PointerType>(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<<Log2AlignVal));
+ break;
+ }
case Instruction::Store: {
if (!isa<PointerType>(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<CastInst>(I) || isa<InvokeInst>(I) ||
- isa<CmpInst>(I) || isa<VAArgInst>(I) || Opcode == 58)
+ isa<CmpInst>(I) || isa<VAArgInst>(I) || Opcode == 58 ||
+ Opcode == 62 || Opcode == 63)
HasExtraArg = true;
if (const AllocationInst *AI = dyn_cast<AllocationInst>(I))
HasExtraArg = AI->getAlignment() != 0;
@@ -468,6 +469,12 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I,
} else if (const AllocationInst *AI = dyn_cast<AllocationInst>(I)) {
if (AI->getAlignment())
output_vbr((unsigned)Log2_32(AI->getAlignment())+1);
+ } else if (Opcode == 62) { // Attributed load
+ output_vbr((unsigned)(((Log2_32(cast<LoadInst>(I)->getAlignment())+1)<<1)
+ + (cast<LoadInst>(I)->isVolatile() ? 1 : 0)));
+ } else if (Opcode == 63) { // Attributed store
+ output_vbr((unsigned)(((Log2_32(cast<StoreInst>(I)->getAlignment())+1)<<1)
+ + (cast<StoreInst>(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<CallInst>(&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<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) {
- Opcode = 62;
- } else if (isa<StoreInst>(I) && cast<StoreInst>(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<InvokeInst>(I)) {
// Invoke escape seq has at least 4 operands to encode.
++NumOperands;
+ } else if (const LoadInst *LI = dyn_cast<LoadInst>(&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<StoreInst>(&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<LoadInst>(I) && cast<LoadInst>(I).getAlignment()) {
+ Out << ", align " << cast<LoadInst>(I).getAlignment();
+ } else if (isa<StoreInst>(I) && cast<StoreInst>(I).getAlignment()) {
+ Out << ", align " << cast<StoreInst>(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<PointerType>(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<PointerType>(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<PointerType>(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<PointerType>(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<PointerType>(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<PointerType>(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<PointerType>(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<PointerType>(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<PointerType>(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
//===----------------------------------------------------------------------===//