PR400 work phase 1. Add attributed load/store instructions for volatile/align to...
authorChristopher Lamb <christopher.lamb@gmail.com>
Sun, 22 Apr 2007 19:24:39 +0000 (19:24 +0000)
committerChristopher Lamb <christopher.lamb@gmail.com>
Sun, 22 Apr 2007 19:24:39 +0000 (19:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36349 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Instructions.h
lib/AsmParser/llvmAsmParser.y
lib/Bytecode/Reader/Reader.cpp
lib/Bytecode/Writer/Writer.cpp
lib/VMCore/AsmWriter.cpp
lib/VMCore/Instructions.cpp

index 3a59e58b01807729b40de6a086fa535ec2cf48b5..61d0efafe5f49f245a053d437dfb68865af9dbb2 100644 (file)
@@ -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); }
index 9b5cc5abfd5bf5faf53bdd9e76650e0dcc6ba7a0..2b08d3afa1b845e639967bb89e0810043631bc2c 100644 (file)
@@ -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 {
index 4cb67c3156540fdd59d4f706f29e976f7db3843e..7ac784ecc7c6c839f135ee777d25cc37a6c1189c 100644 (file)
@@ -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!");
index 4688e69ef2fba469f5778e426b43ed8256c5bfa1..12724dd6becdb4c6e1eb8aa52f47df70df6c3a49 100644 (file)
@@ -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
index 63ec8e423e5d8a5c4c67958deb6d506069ee7dd9..90f0198b570088bed04bf5fdfce35c23daf18e1e 100644 (file)
@@ -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";
index e0c2a5e6bb68bfa02aca92dbe918e2df2375ef94..2bd350080e3273a6717767abb530fd7b449305d4 100644 (file)
@@ -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
 //===----------------------------------------------------------------------===//