Index: llvm/lib/Analysis/InstructionSimplify.cpp
===================================================================
--- llvm/lib/Analysis/InstructionSimplify.cpp
+++ llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2635,11 +2635,29 @@
       Opts.NullIsUnknownSize =
           NullPointerIsDefined(cast<AllocaInst>(LHS)->getFunction());
       if (getObjectSize(LHS, LHSSize, DL, TLI, Opts) &&
-          getObjectSize(RHS, RHSSize, DL, TLI, Opts) &&
-          !LHSOffset.isNegative() && !RHSOffset.isNegative() &&
-          LHSOffset.ult(LHSSize) && RHSOffset.ult(RHSSize)) {
-        return ConstantInt::get(GetCompareTy(LHS),
-                                !CmpInst::isTrueWhenEqual(Pred));
+          getObjectSize(RHS, RHSSize, DL, TLI, Opts)) {
+        auto CanNotOverlap = [&]() -> bool {
+          if (!LHSOffset.isNegative() && !RHSOffset.isNegative()) {
+            return ((LHSOffset.ult(LHSSize) ||
+                     (LHSOffset - LHSSize).ult(RHSOffset)) &&
+                    (RHSOffset.ult(RHSSize) ||
+                     (RHSOffset - RHSSize).ult(LHSOffset)));
+          }
+          auto LAbs = LHSOffset.sext(LHSOffset.getBitWidth() + 1).abs();
+          auto RAbs = RHSOffset.sext(RHSOffset.getBitWidth() + 1).abs();
+          if (LHSOffset.isNegative() && RHSOffset.isNegative())
+            // TODO: Add corresponding max offset in other case (inverse
+            // of the positive version)
+            return (LAbs.ult(RHSSize) && RAbs.ult(LHSSize));
+          if (!LHSOffset.isNegative() && RHSOffset.isNegative())
+            return (LAbs + RAbs).ult(LHSSize);
+          if (LHSOffset.isNegative() && !RHSOffset.isNegative())
+            return (LAbs + RAbs).ult(RHSSize);
+          llvm_unreachable("");
+        };
+        if (CanNotOverlap())
+          return ConstantInt::get(GetCompareTy(LHS),
+                                  !CmpInst::isTrueWhenEqual(Pred));
       }
     }
 
Index: llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
===================================================================
--- llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
+++ llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
@@ -42,15 +42,10 @@
   ret i1 %res
 }
 
-; FIXME: Can't be equal
+; Can't be equal
 define i1 @positive_non_equal_end() {
 ; CHECK-LABEL: @positive_non_equal_end(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, i8* [[A]], i64 4
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, i8* [[B]], i64 4
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8* [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
@@ -144,15 +139,10 @@
   ret i1 %res
 }
 
-; FIXME: Can't be equal
+; Can't be equal
 define i1 @mixed_offsets1() {
 ; CHECK-LABEL: @mixed_offsets1(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, i8* [[A]], i64 -1
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, i8* [[B]], i64 2
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8* [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
@@ -162,15 +152,10 @@
   ret i1 %res
 }
 
-; FIXME: Can't be equal
+; Can't be equal
 define i1 @mixed_offsets2() {
 ; CHECK-LABEL: @mixed_offsets2(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, i8* [[A]], i64 1
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, i8* [[B]], i64 -2
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8* [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
@@ -180,15 +165,10 @@
   ret i1 %res
 }
 
-; FIXME: Can't be equal
+; Can't be equal
 define i1 @negative_in_other() {
 ; CHECK-LABEL: @negative_in_other(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, i8* [[A]], i64 -3
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, i8* [[B]], i64 -2
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne i8* [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
Index: llvm/test/Transforms/InstSimplify/past-the-end.ll
===================================================================
--- llvm/test/Transforms/InstSimplify/past-the-end.ll
+++ llvm/test/Transforms/InstSimplify/past-the-end.ll
@@ -58,12 +58,7 @@
 
 define zeroext i1 @both_past_the_end_alloca() {
 ; CHECK-LABEL: @both_past_the_end_alloca(
-; CHECK:         [[M:%.*]] = alloca i32
-; CHECK-NEXT:    [[N:%.*]] = alloca i32
-; CHECK-NEXT:    [[X:%.*]] = getelementptr i32, i32* [[M]], i32 1
-; CHECK-NEXT:    [[Y:%.*]] = getelementptr i32, i32* [[N]], i32 1
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32* [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = alloca i32
   %n = alloca i32