Index: llvm/trunk/include/llvm/IR/Value.h
===================================================================
--- llvm/trunk/include/llvm/IR/Value.h
+++ llvm/trunk/include/llvm/IR/Value.h
@@ -482,6 +482,17 @@
                          static_cast<const Value *>(this)->stripPointerCasts());
   }
 
+  /// \brief Strip off pointer casts, all-zero GEPs, aliases and barriers.
+  ///
+  /// Returns the original uncasted value.  If this is called on a non-pointer
+  /// value, it returns 'this'. This function should be used only in
+  /// Alias analysis.
+  const Value *stripPointerCastsAndBarriers() const;
+  Value *stripPointerCastsAndBarriers() {
+    return const_cast<Value *>(
+        static_cast<const Value *>(this)->stripPointerCastsAndBarriers());
+  }
+
   /// \brief Strip off pointer casts and all-zero GEPs.
   ///
   /// Returns the original uncasted value.  If this is called on a non-pointer
Index: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
===================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
@@ -924,8 +924,8 @@
                                             uint64_t V2Size,
                                             const DataLayout &DL) {
 
-  assert(GEP1->getPointerOperand()->stripPointerCasts() ==
-             GEP2->getPointerOperand()->stripPointerCasts() &&
+  assert(GEP1->getPointerOperand()->stripPointerCastsAndBarriers() ==
+             GEP2->getPointerOperand()->stripPointerCastsAndBarriers() &&
          GEP1->getPointerOperandType() == GEP2->getPointerOperandType() &&
          "Expected GEPs with the same pointer operand");
 
@@ -1184,8 +1184,8 @@
     // If we know the two GEPs are based off of the exact same pointer (and not
     // just the same underlying object), see if that tells us anything about
     // the resulting pointers.
-    if (GEP1->getPointerOperand()->stripPointerCasts() ==
-            GEP2->getPointerOperand()->stripPointerCasts() &&
+    if (GEP1->getPointerOperand()->stripPointerCastsAndBarriers() ==
+            GEP2->getPointerOperand()->stripPointerCastsAndBarriers() &&
         GEP1->getPointerOperandType() == GEP2->getPointerOperandType()) {
       AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL);
       // If we couldn't find anything interesting, don't abandon just yet.
@@ -1500,8 +1500,8 @@
     return NoAlias;
 
   // Strip off any casts if they exist.
-  V1 = V1->stripPointerCasts();
-  V2 = V2->stripPointerCasts();
+  V1 = V1->stripPointerCastsAndBarriers();
+  V2 = V2->stripPointerCastsAndBarriers();
 
   // If V1 or V2 is undef, the result is NoAlias because we can always pick a
   // value for undef that aliases nothing in the program.
Index: llvm/trunk/lib/IR/Value.cpp
===================================================================
--- llvm/trunk/lib/IR/Value.cpp
+++ llvm/trunk/lib/IR/Value.cpp
@@ -432,6 +432,7 @@
 enum PointerStripKind {
   PSK_ZeroIndices,
   PSK_ZeroIndicesAndAliases,
+  PSK_ZeroIndicesAndAliasesAndBarriers,
   PSK_InBoundsConstantIndices,
   PSK_InBounds
 };
@@ -450,6 +451,7 @@
     if (auto *GEP = dyn_cast<GEPOperator>(V)) {
       switch (StripKind) {
       case PSK_ZeroIndicesAndAliases:
+      case PSK_ZeroIndicesAndAliasesAndBarriers:
       case PSK_ZeroIndices:
         if (!GEP->hasAllZeroIndices())
           return V;
@@ -472,12 +474,20 @@
         return V;
       V = GA->getAliasee();
     } else {
-      if (auto CS = ImmutableCallSite(V))
+      if (auto CS = ImmutableCallSite(V)) {
         if (const Value *RV = CS.getReturnedArgOperand()) {
           V = RV;
           continue;
         }
-
+        // The result of invariant.group.barrier must alias it's argument,
+        // but it can't be marked with returned attribute, that's why it needs
+        // special case.
+        if (StripKind == PSK_ZeroIndicesAndAliasesAndBarriers &&
+            CS.getIntrinsicID() == Intrinsic::invariant_group_barrier) {
+          V = CS.getArgOperand(0);
+          continue;
+        }
+      }
       return V;
     }
     assert(V->getType()->isPointerTy() && "Unexpected operand type!");
@@ -499,6 +509,11 @@
   return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
 }
 
+const Value *Value::stripPointerCastsAndBarriers() const {
+  return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndBarriers>(
+      this);
+}
+
 const Value *
 Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
                                                  APInt &Offset) const {
Index: llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll
===================================================================
--- llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll
+++ llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll
@@ -0,0 +1,15 @@
+; RUN: opt -S -gvn < %s | FileCheck %s
+; RUN: opt -S -newgvn < %s | FileCheck %s
+; RUN: opt -S -O3 < %s | FileCheck %s
+
+; This test check if optimizer is not proving equality based on mustalias
+; CHECK-LABEL: define void @dontProveEquality(i8* %a) 
+define void @dontProveEquality(i8* %a) {
+  %b = call i8* @llvm.invariant.group.barrier(i8* %a)
+  %r = i1 icmp eq i8* %b, i8* %a
+;CHECK: call void @use(%r)
+  call void @use(%r)
+}
+
+declare void @use(i1)
+declare i8* @llvm.invariant.group.barrier(i8 *)
Index: llvm/trunk/test/Transforms/GVN/invariant.group.ll
===================================================================
--- llvm/trunk/test/Transforms/GVN/invariant.group.ll
+++ llvm/trunk/test/Transforms/GVN/invariant.group.ll
@@ -237,15 +237,16 @@
     ret i8 %a
 }
 
-; CHECK-LABEL: define i8 @unoptimizable4() {
-define i8 @unoptimizable4() {
+; CHECK-LABEL: define i8 @optimizable4() {
+define i8 @optimizable4() {
 entry:
     %ptr = alloca i8
     store i8 42, i8* %ptr, !invariant.group !0
     %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
+; CHECK-NOT: load
     %a = load i8, i8* %ptr2, !invariant.group !0
     
-; CHECK: ret i8 %a
+; CHECK: ret i8 42
     ret i8 %a
 }
 
@@ -314,8 +315,9 @@
     store i8 %unknownValue, i8* %ptr, !invariant.group !0 
 
     %newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
-    %d = load i8, i8* %newPtr2, !invariant.group !0  ; Can't step through invariant.group.barrier to get value of %ptr
-; CHECK: ret i8 %d
+; CHECK-NOT: load
+    %d = load i8, i8* %newPtr2, !invariant.group !0
+; CHECK: ret i8 %unknownValue
     ret i8 %d
 }