Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -709,6 +709,8 @@
     return QualType::isConstant(*this, Ctx);
   }
 
+  bool isWriteOnce(ASTContext &Ctx);
+
   /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
   bool isPODType(ASTContext &Context) const;
 
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -1913,6 +1913,19 @@
   }
 }
 
+bool QualType::isWriteOnce(ASTContext &Context) {
+
+	if (!Context.getLangOpts().CPlusPlus ||
+			!isConstant(Context) || getTypePtr()->isReferenceType())
+    return false;
+
+  if (const CXXRecordDecl *Record
+        = Context.getBaseElementType(*this)->getAsCXXRecordDecl())
+  	return !Record->hasMutableFields();
+
+  return true;
+}
+
 bool QualType::isPODType(ASTContext &Context) const {
   // C++11 has a more relaxed definition of POD.
   if (Context.getLangOpts().CPlusPlus11)
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -524,6 +524,20 @@
       CGF.EmitLifetimeEnd(Size, Addr);
     }
   };
+
+  /// A cleanup to call @llvm.invariant.end.
+  class CallInvariantEnd : public EHScopeStack::Cleanup {
+    llvm::CallInst *StartInst;
+    llvm::Value *Addr;
+    llvm::Value *Size;    // TODO: Is this even necessary?
+  public:
+    CallInvariantEnd(llvm::CallInst *C, llvm::Value *addr, llvm::Value *size)
+      : StartInst(C), Addr(addr), Size(size) {}
+
+    void Emit(CodeGenFunction &CGF, Flags flags) override {
+      CGF.EmitInvariantEnd(StartInst, Size, Addr);
+    }
+  };
 }
 
 /// EmitAutoVarWithLifetime - Does the setup required for an automatic
@@ -842,12 +856,38 @@
          canEmitInitWithFewStoresAfterMemset(Init, StoreBudget);
 }
 
+
+/// Emit the code necessary to initialize the given global variable.
+void CodeGenFunction::MarkWriteOnceWritten(const VarDecl& D,
+                                           llvm::Value *Addr) {
+	auto *GV = dyn_cast<llvm::GlobalVariable>(Addr);
+	auto *AI = dyn_cast<llvm::AllocaInst>(Addr);
+
+	// Only GlobalVariable's and AllocaInst's can be writeonce.
+	// Exit if the given address is none of these.
+	if (!GV && !AI) return;
+
+	// If the address is writeonce, then emit @llvm.invariant.start() intrinsic.
+	// Then, for non-global variables, push the emission of the
+	// @llvm.invariant.end() intrinsic onto the cleanup stack.
+	if ((GV && GV->isWriteOnce()) || (AI && AI->isWriteOnce())) {
+	  CodeGenModule::InvariantArgs Args = EmitInvariantStart(D, Addr);
+
+		if (AI && Args.StartInst) {
+		  assert(!GV && "Can't have it both ways.");
+			EHStack.pushCleanup<CallInvariantEnd>(NormalCleanup, Args.StartInst,
+			                                      Args.Addr, Args.Size);
+		}
+	}
+}
+
 /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
 /// variable declaration with auto, register, or no storage class specifier.
 /// These turn into simple stack objects, or GlobalValues depending on target.
 void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
   AutoVarEmission emission = EmitAutoVarAlloca(D);
   EmitAutoVarInit(emission);
+	MarkWriteOnceWritten(D, emission.Address);
   EmitAutoVarCleanups(emission);
 }
 
@@ -880,6 +920,49 @@
   C->setDoesNotThrow();
 }
 
+/// Emit code to cause the variable at the given address to be considered as
+/// constant from this point onwards.
+CodeGenModule::InvariantArgs
+CodeGenFunction::EmitInvariantStart(const VarDecl &D, llvm::Value *Addr) {
+  // Don't emit the intrinsic if we're not optimizing.
+  if (!CGM.getCodeGenOpts().OptimizationLevel)
+    return CodeGenModule::InvariantArgs{nullptr, 0, nullptr};
+
+  // Grab the llvm.invariant.start intrinsic.
+  llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
+  llvm::Constant *InvariantStart = CGM.getIntrinsic(InvStartID);
+
+  // Emit a call with the size in bytes of the object.
+  CharUnits WidthChars = getContext().getTypeSizeInChars(D.getType());
+  uint64_t Width = WidthChars.getQuantity();
+
+  llvm::Value *Size;
+  if (llvm::Constant* CAddr = dyn_cast<llvm::Constant>(Addr)) {
+    Size = llvm::ConstantInt::getSigned(Int64Ty, Width);
+    Addr = llvm::ConstantExpr::getBitCast(CAddr, Int8PtrTy);
+  }
+  else {
+    //Width = CGM.getDataLayout().getTypeAllocSize(LTy);
+    Size = llvm::ConstantInt::get(Int64Ty, Width);
+    Addr = Builder.CreateBitCast(Addr, Int8PtrTy);
+  }
+  llvm::CallInst *C = Builder.CreateCall(InvariantStart, {Size, Addr});
+  C->setDoesNotThrow();
+
+  return CodeGenModule::InvariantArgs{C, Size, Addr};
+}
+
+void CodeGenFunction::EmitInvariantEnd(llvm::CallInst *Start,
+                                       llvm::Value *Size, llvm::Value *Addr) {
+  // Grab the llvm.invariant.end intrinsic.
+  llvm::Intrinsic::ID InvEndID = llvm::Intrinsic::invariant_end;
+  llvm::Constant *InvariantEnd = CGM.getIntrinsic(InvEndID);
+
+  // Emit a call with the size in bytes of the object.
+  llvm::CallInst *C = Builder.CreateCall(InvariantEnd, {Start, Size, Addr});
+  C->setDoesNotThrow();
+}
+
 /// EmitAutoVarAlloca - Emit the alloca and debug information for a
 /// local variable.  Does not emit initialization or destruction.
 CodeGenFunction::AutoVarEmission
@@ -949,7 +1032,8 @@
           // to this variable. Set it to zero to indicate that NRVO was not
           // applied.
           llvm::Value *Zero = Builder.getFalse();
-          llvm::Value *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+          llvm::AllocaInst *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+          NRVOFlag->setWriteOnce(Ty.isWriteOnce(getContext()));
           EnsureInsertPoint();
           Builder.CreateStore(Zero, NRVOFlag);
 
@@ -964,6 +1048,7 @@
 
       llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
       Alloc->setName(D.getName());
+      Alloc->setWriteOnce(Ty.isWriteOnce(getContext()));
 
       CharUnits allocaAlignment = alignment;
       if (isByRef)
@@ -986,7 +1071,8 @@
 
     if (!DidCallStackSave) {
       // Save the stack.
-      llvm::Value *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack");
+      llvm::AllocaInst *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack");
+      Stack->setWriteOnce(Ty.isWriteOnce(getContext()));
 
       llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
       llvm::Value *V = Builder.CreateCall(F);
@@ -1009,6 +1095,7 @@
     // Allocate memory for the array.
     llvm::AllocaInst *vla = Builder.CreateAlloca(llvmTy, elementCount, "vla");
     vla->setAlignment(alignment.getQuantity());
+    vla->setWriteOnce(Ty.isWriteOnce(getContext()));
 
     DeclPtr = vla;
   }
@@ -1678,6 +1765,7 @@
         llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
                                                    D.getName() + ".addr");
         Alloc->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+        Alloc->setWriteOnce(Ty.isWriteOnce(getContext()));
         LValue lv = MakeAddrLValue(Alloc, Ty, getContext().getDeclAlign(&D));
         EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
         LocalAddr = Builder.CreateLoad(Alloc);
@@ -1721,6 +1809,7 @@
     llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
                                                D.getName() + ".addr");
     Alloc->setAlignment(Align.getQuantity());
+    Alloc->setWriteOnce(Ty.isWriteOnce(getContext()));
     DeclPtr = Alloc;
     DoStore = true;
   }
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -112,26 +112,6 @@
   CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
 }
 
-/// Emit code to cause the variable at the given address to be considered as
-/// constant from this point onwards.
-static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
-                              llvm::Constant *Addr) {
-  // Don't emit the intrinsic if we're not optimizing.
-  if (!CGF.CGM.getCodeGenOpts().OptimizationLevel)
-    return;
-
-  // Grab the llvm.invariant.start intrinsic.
-  llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
-  llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID);
-
-  // Emit a call with the size in bytes of the object.
-  CharUnits WidthChars = CGF.getContext().getTypeSizeInChars(D.getType());
-  uint64_t Width = WidthChars.getQuantity();
-  llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, Width),
-                           llvm::ConstantExpr::getBitCast(Addr, CGF.Int8PtrTy)};
-  CGF.Builder.CreateCall(InvariantStart, Args);
-}
-
 void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
                                                llvm::Constant *DeclPtr,
                                                bool PerformInit) {
@@ -169,9 +149,13 @@
           PerformInit, this);
     if (PerformInit)
       EmitDeclInit(*this, D, DeclPtr);
-    if (CGM.isTypeConstant(D.getType(), true))
-      EmitDeclInvariant(*this, D, DeclPtr);
-    else
+    if (CGM.isTypeConstant(D.getType(), true)) {
+      // Generate the @llvm.invariant.start intrinsic call if DeclPtr is
+      // not a writeonce. We'll do the same for writeonce addresses later.
+      llvm::GlobalVariable* GV = dyn_cast<llvm::GlobalVariable>(DeclPtr);
+      if (GV && !GV->isWriteOnce())
+        (void) EmitInvariantStart(D, DeclPtr);
+    } else
       EmitDeclDestroy(*this, D, DeclPtr);
     return;
   }
@@ -491,6 +475,7 @@
   } else {
     EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
   }
+	MarkWriteOnceWritten(*D, Addr);
 
   FinishFunction();
 }
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -1408,7 +1408,7 @@
 
   // Optimize the slot if possible.
   CheckAggExprForMemSetUse(Slot, E, *this);
- 
+
   AggExprEmitter(*this, Slot, Slot.isIgnored()).Visit(const_cast<Expr*>(E));
 }
 
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -1788,6 +1788,8 @@
 
   llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
   void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+  void EmitInvariantEnd(llvm::CallInst *C,
+                        llvm::Value *Size, llvm::Value *Addr);
 
   llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
   void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -2760,6 +2762,9 @@
   AddInitializerToStaticVarDecl(const VarDecl &D,
                                 llvm::GlobalVariable *GV);
 
+  void MarkWriteOnceWritten(const VarDecl& D, llvm::Value *Addr);
+  CodeGenModule::InvariantArgs EmitInvariantStart(const VarDecl &D,
+                                                  llvm::Value *Addr);
 
   /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++
   /// variable with global storage.
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -277,6 +277,14 @@
 
   typedef std::vector<Structor> CtorList;
 
+  struct InvariantArgs {
+    llvm::CallInst *StartInst;
+    llvm::Value *Size;
+    llvm::Value *Addr;
+    InvariantArgs(llvm::CallInst *C, llvm::Value *size, llvm::Value *addr)
+    : StartInst(C), Size(size), Addr(addr) {}
+  };
+
 private:
   ASTContext &Context;
   const LangOptions &LangOpts;
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -2115,6 +2115,9 @@
     // common vars aren't constant even if declared const.
     GV->setConstant(false);
 
+  // Mark const variables 'writeonce', if global is not 'constant'.
+  GV->setWriteOnce(!GV->isConstant() && D->getType().isWriteOnce(Context));
+
   setNonAliasAttributes(D, GV);
 
   if (D->getTLSKind() && !GV->isThreadLocal()) {