Index: include/llvm/CodeGen/SelectionDAG.h
===================================================================
--- include/llvm/CodeGen/SelectionDAG.h
+++ include/llvm/CodeGen/SelectionDAG.h
@@ -1156,6 +1156,10 @@
   /// either of the specified value types.
   SDValue CreateStackTemporary(EVT VT1, EVT VT2);
 
+  SDValue FoldSymbolOffset(unsigned Opcode, EVT VT,
+                           const GlobalAddressSDNode *GA,
+                           const SDNode *N2);
+
   SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
                                  SDNode *Cst1, SDNode *Cst2);
 
Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -390,6 +390,12 @@
     /// consecutive chains.
     bool findBetterNeighborChains(StoreSDNode *St);
 
+    /// Test whether the given value is a constant int or similar node.
+    SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N);
+
+    /// Match "(X shl/srl V1) & V2" where V2 may not be present.
+    bool MatchRotateHalf(SDValue Op, SDValue &Shift, SDValue &Mask);
+
     /// Holds a pointer to an LSBaseSDNode as well as information on where it
     /// is located in a sequence of memory operations connected by a chain.
     struct MemOpLink {
@@ -765,11 +771,17 @@
 
 // \brief Returns the SDNode if it is a constant integer BuildVector
 // or constant integer.
-static SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N) {
+SDNode *DAGCombiner::isConstantIntBuildVectorOrConstantInt(SDValue N) {
   if (isa<ConstantSDNode>(N))
     return N.getNode();
   if (ISD::isBuildVectorOfConstantSDNodes(N.getNode()))
     return N.getNode();
+  // Treat a GlobalAddress supporting constant offset folding as a
+  // constant integer.
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N))
+    if (GA->getOpcode() == ISD::GlobalAddress &&
+        TLI.isOffsetFoldingLegal(GA))
+      return GA;
   return nullptr;
 }
 
@@ -1657,34 +1669,28 @@
     return N0;
   if (N1.getOpcode() == ISD::UNDEF)
     return N1;
-  // fold (add c1, c2) -> c1+c2
-  ConstantSDNode *N0C = getAsNonOpaqueConstant(N0);
-  ConstantSDNode *N1C = getAsNonOpaqueConstant(N1);
-  if (N0C && N1C)
-    return DAG.FoldConstantArithmetic(ISD::ADD, SDLoc(N), VT, N0C, N1C);
-  // canonicalize constant to RHS
-  if (isConstantIntBuildVectorOrConstantInt(N0) &&
-     !isConstantIntBuildVectorOrConstantInt(N1))
-    return DAG.getNode(ISD::ADD, SDLoc(N), VT, N1, N0);
+  if (isConstantIntBuildVectorOrConstantInt(N0)) {
+    // canonicalize constant to RHS
+    if (!isConstantIntBuildVectorOrConstantInt(N1))
+      return DAG.getNode(ISD::ADD, SDLoc(N), VT, N1, N0);
+    // fold (add c1, c2) -> c1+c2
+    return DAG.FoldConstantArithmetic(ISD::ADD, SDLoc(N), VT,
+                                      N0.getNode(), N1.getNode());
+  }
   // fold (add x, 0) -> x
   if (isNullConstant(N1))
     return N0;
-  // fold (add Sym, c) -> Sym+c
-  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0))
-    if (!LegalOperations && TLI.isOffsetFoldingLegal(GA) && N1C &&
-        GA->getOpcode() == ISD::GlobalAddress)
-      return DAG.getGlobalAddress(GA->getGlobal(), SDLoc(N1C), VT,
-                                  GA->getOffset() +
-                                    (uint64_t)N1C->getSExtValue());
   // fold ((c1-A)+c2) -> (c1+c2)-A
-  if (N1C && N0.getOpcode() == ISD::SUB)
-    if (ConstantSDNode *N0C = getAsNonOpaqueConstant(N0.getOperand(0))) {
-      SDLoc DL(N);
-      return DAG.getNode(ISD::SUB, DL, VT,
-                         DAG.getConstant(N1C->getAPIntValue()+
-                                         N0C->getAPIntValue(), DL, VT),
-                         N0.getOperand(1));
-    }
+  if (ConstantSDNode *N1C = getAsNonOpaqueConstant(N1)) {
+    if (N0.getOpcode() == ISD::SUB)
+      if (ConstantSDNode *N0C = getAsNonOpaqueConstant(N0.getOperand(0))) {
+        SDLoc DL(N);
+        return DAG.getNode(ISD::SUB, DL, VT,
+                           DAG.getConstant(N1C->getAPIntValue()+
+                                           N0C->getAPIntValue(), DL, VT),
+                           N0.getOperand(1));
+      }
+  }
   // reassociate add
   if (SDValue RADD = ReassociateOps(ISD::ADD, SDLoc(N), N0, N1))
     return RADD;
@@ -1879,11 +1885,14 @@
   // FIXME: Refactor this and xor and other similar operations together.
   if (N0 == N1)
     return tryFoldToZero(SDLoc(N), TLI, VT, DAG, LegalOperations, LegalTypes);
-  // fold (sub c1, c2) -> c1-c2
+  if (isConstantIntBuildVectorOrConstantInt(N0) &&
+      isConstantIntBuildVectorOrConstantInt(N1)) {
+    // fold (sub c1, c2) -> c1-c2
+    return DAG.FoldConstantArithmetic(ISD::SUB, SDLoc(N), VT,
+                                      N0.getNode(), N1.getNode());
+  }
   ConstantSDNode *N0C = getAsNonOpaqueConstant(N0);
   ConstantSDNode *N1C = getAsNonOpaqueConstant(N1);
-  if (N0C && N1C)
-    return DAG.FoldConstantArithmetic(ISD::SUB, SDLoc(N), VT, N0C, N1C);
   // fold (sub x, c) -> (add x, -c)
   if (N1C) {
     SDLoc DL(N);
@@ -3817,7 +3826,7 @@
 }
 
 /// Match "(X shl/srl V1) & V2" where V2 may not be present.
-static bool MatchRotateHalf(SDValue Op, SDValue &Shift, SDValue &Mask) {
+bool DAGCombiner::MatchRotateHalf(SDValue Op, SDValue &Shift, SDValue &Mask) {
   if (Op.getOpcode() == ISD::AND) {
     if (isConstantIntBuildVectorOrConstantInt(Op.getOperand(1))) {
       Mask = Op.getOperand(1);
@@ -10940,9 +10949,23 @@
   }
 
   /// Parses tree in Ptr for base, index, offset addresses.
-  static BaseIndexOffset match(SDValue Ptr) {
+  static BaseIndexOffset match(SDValue Ptr, SelectionDAG &DAG) {
     bool IsIndexSignExt = false;
 
+    // Split up a folded GlobalAddress+Offset into its component parts.
+    if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Ptr))
+      if (GA->getOpcode() == ISD::GlobalAddress && GA->getOffset() != 0) {
+        return BaseIndexOffset(DAG.getGlobalAddress(GA->getGlobal(),
+                                                    SDLoc(GA),
+                                                    GA->getValueType(0),
+                                                    /*Offset=*/0,
+                                                    /*isTargetGA=*/false,
+                                                    GA->getTargetFlags()),
+                               SDValue(),
+                               GA->getOffset(),
+                               IsIndexSignExt);
+      }
+
     // We only can pattern match BASE + INDEX + OFFSET. If Ptr is not an ADD
     // instruction, then it could be just the BASE or everything else we don't
     // know how to handle. Just use Ptr as BASE and give up.
@@ -11215,7 +11238,7 @@
     SmallVectorImpl<LSBaseSDNode*> &AliasLoadNodes) {
   // This holds the base pointer, index, and the offset in bytes from the base
   // pointer.
-  BaseIndexOffset BasePtr = BaseIndexOffset::match(St->getBasePtr());
+  BaseIndexOffset BasePtr = BaseIndexOffset::match(St->getBasePtr(), DAG);
 
   // We must have a base and an offset.
   if (!BasePtr.Base.getNode())
@@ -11253,7 +11276,7 @@
         if (OtherST->getMemoryVT() != MemVT)
           continue;
 
-        BaseIndexOffset Ptr = BaseIndexOffset::match(OtherST->getBasePtr());
+        BaseIndexOffset Ptr = BaseIndexOffset::match(OtherST->getBasePtr(), DAG);
 
         if (Ptr.equalBaseIndex(BasePtr))
           StoreNodes.push_back(MemOpLink(OtherST, Ptr.Offset, Seq++));
@@ -11269,7 +11292,7 @@
       break;
 
     // Find the base pointer and offset for this memory node.
-    BaseIndexOffset Ptr = BaseIndexOffset::match(Index->getBasePtr());
+    BaseIndexOffset Ptr = BaseIndexOffset::match(Index->getBasePtr(), DAG);
 
     // Check that the base pointer is the same as the original one.
     if (!Ptr.equalBaseIndex(BasePtr))
@@ -11557,7 +11580,7 @@
     if (Ld->getMemoryVT() != MemVT)
       break;
 
-    BaseIndexOffset LdPtr = BaseIndexOffset::match(Ld->getBasePtr());
+    BaseIndexOffset LdPtr = BaseIndexOffset::match(Ld->getBasePtr(), DAG);
     // If this is not the first ptr that we check.
     if (LdBasePtr.Base.getNode()) {
       // The base ptr must be the same.
@@ -14716,7 +14739,7 @@
 bool DAGCombiner::findBetterNeighborChains(StoreSDNode* St) {
   // This holds the base pointer, index, and the offset in bytes from the base
   // pointer.
-  BaseIndexOffset BasePtr = BaseIndexOffset::match(St->getBasePtr());
+  BaseIndexOffset BasePtr = BaseIndexOffset::match(St->getBasePtr(), DAG);
 
   // We must have a base and an offset.
   if (!BasePtr.Base.getNode())
@@ -14742,7 +14765,7 @@
       break;
 
     // Find the base pointer and offset for this memory node.
-    BaseIndexOffset Ptr = BaseIndexOffset::match(Index->getBasePtr());
+    BaseIndexOffset Ptr = BaseIndexOffset::match(Index->getBasePtr(), DAG);
 
     // Check that the base pointer is the same as the original one.
     if (!Ptr.equalBaseIndex(BasePtr))
Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -3263,6 +3263,26 @@
   return getConstant(Folded.first, DL, VT);
 }
 
+SDValue SelectionDAG::FoldSymbolOffset(unsigned Opcode, EVT VT,
+                                       const GlobalAddressSDNode *GA,
+                                       const SDNode *N2) {
+  if (GA->getOpcode() != ISD::GlobalAddress)
+    return SDValue();
+  if (!TLI->isOffsetFoldingLegal(GA))
+    return SDValue();
+  const ConstantSDNode *Cst2 = dyn_cast<ConstantSDNode>(N2);
+  if (!Cst2)
+    return SDValue();
+  int64_t Offset = Cst2->getSExtValue();
+  switch (Opcode) {
+  case ISD::ADD: break;
+  case ISD::SUB: Offset = -uint64_t(Offset); break;
+  default: return SDValue();
+  }
+  return getGlobalAddress(GA->getGlobal(), SDLoc(Cst2), VT,
+                          GA->getOffset() + uint64_t(Offset));
+}
+
 SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT,
                                              SDNode *Cst1, SDNode *Cst2) {
   // If the opcode is a target-specific ISD node, there's nothing we can
@@ -3289,6 +3309,12 @@
     }
   }
 
+  // fold (add Sym, c) -> Sym+c
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Cst1))
+    return FoldSymbolOffset(Opcode, VT, GA, Cst2);
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Cst2))
+    return FoldSymbolOffset(Opcode, VT, GA, Cst1);
+
   // For vectors extract each constant element into Inputs so we can constant
   // fold them individually.
   BuildVectorSDNode *BV1 = dyn_cast<BuildVectorSDNode>(Cst1);
Index: test/CodeGen/WebAssembly/address-offsets.ll
===================================================================
--- test/CodeGen/WebAssembly/address-offsets.ll
+++ test/CodeGen/WebAssembly/address-offsets.ll
@@ -0,0 +1,673 @@
+; RUN: llc < %s -asm-verbose=false | FileCheck %s
+
+; Test folding constant offsets and symbols into load and store addresses under
+; a variety of circumstances.
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+@g = external global [0 x i32], align 4
+
+; CHECK-LABEL: load_test0:
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 0{{$}}
+; CHECK-NEXT: i32.load  $push1=, g+40($pop0){{$}}
+; CHECK-NEXT: return    $pop1{{$}}
+define i32 @load_test0() {
+  %t = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test0_noinbounds:
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 0{{$}}
+; CHECK-NEXT: i32.load  $push1=, g+40($pop0){{$}}
+; CHECK-NEXT: return    $pop1{{$}}
+
+define i32 @load_test0_noinbounds() {
+  %t = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test1:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test1(i32 %n) {
+  %add = add nsw i32 %n, 10
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test2:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test2(i32 %n) {
+  %add = add nsw i32 10, %n
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test3:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test3(i32 %n) {
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  %t = load i32, i32* %add.ptr1, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test4:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test4(i32 %n) {
+  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
+  %t = load i32, i32* %add.ptr, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test5:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test5(i32 %n) {
+  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
+  %t = load i32, i32* %add.ptr, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test6:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test6(i32 %n) {
+  %add = add nsw i32 %n, 10
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  %t = load i32, i32* %add.ptr, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test7:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test7(i32 %n) {
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  %t = load i32, i32* %add.ptr1, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test8:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, g+40($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test8(i32 %n) {
+  %add = add nsw i32 10, %n
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  %t = load i32, i32* %add.ptr, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test9:
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 0{{$}}
+; CHECK-NEXT: i32.load  $push1=, g-40($pop0){{$}}
+; CHECK-NEXT: return    $pop1{{$}}
+define i32 @load_test9() {
+  %t = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 1073741814), align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test10:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.const $push2=, g-40{{$}}
+; CHECK-NEXT: i32.add   $push3=, $pop1, $pop2{{$}}
+; CHECK-NEXT: i32.load  $push4=, 0($pop3){{$}}
+; CHECK-NEXT: return    $pop4{{$}}
+define i32 @load_test10(i32 %n) {
+  %add = add nsw i32 %n, -10
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test11:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.load  $push0=, 40($0){{$}}
+; CHECK-NEXT: return    $pop0{{$}}
+define i32 @load_test11(i32* %p) {
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 10
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test11_noinbounds:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 40{{$}}
+; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, 0($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test11_noinbounds(i32* %p) {
+  %arrayidx = getelementptr i32, i32* %p, i32 10
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test12:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test12(i32* %p, i32 %n) {
+  %add = add nsw i32 %n, 10
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test13:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test13(i32* %p, i32 %n) {
+  %add = add nsw i32 10, %n
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test14:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.load  $push3=, 40($pop2){{$}}
+; CHECK-NEXT: return    $pop3{{$}}
+define i32 @load_test14(i32* %p, i32 %n) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  %t = load i32, i32* %add.ptr1, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test15:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test15(i32* %p, i32 %n) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
+  %t = load i32, i32* %add.ptr1, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test16:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test16(i32* %p, i32 %n) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
+  %t = load i32, i32* %add.ptr1, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test17:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test17(i32* %p, i32 %n) {
+  %add = add nsw i32 %n, 10
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
+  %t = load i32, i32* %add.ptr, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test18:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.load  $push3=, 40($pop2){{$}}
+; CHECK-NEXT: return    $pop3{{$}}
+define i32 @load_test18(i32* %p, i32 %n) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  %t = load i32, i32* %add.ptr1, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test19:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test19(i32* %p, i32 %n) {
+  %add = add nsw i32 10, %n
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
+  %t = load i32, i32* %add.ptr, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test20:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, -40{{$}}
+; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.load  $push2=, 0($pop1){{$}}
+; CHECK-NEXT: return    $pop2{{$}}
+define i32 @load_test20(i32* %p) {
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 -10
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: load_test21:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: result    i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, -40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.load  $push5=, 0($pop4){{$}}
+; CHECK-NEXT: return    $pop5{{$}}
+define i32 @load_test21(i32* %p, i32 %n) {
+  %add = add nsw i32 %n, -10
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
+  %t = load i32, i32* %arrayidx, align 4
+  ret i32 %t
+}
+
+; CHECK-LABEL: store_test0:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop0), $0{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test0(i32 %i) {
+  store i32 %i, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test0_noinbounds:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop0), $0{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test0_noinbounds(i32 %i) {
+  store i32 %i, i32* getelementptr ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test1:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test1(i32 %n, i32 %i) {
+  %add = add nsw i32 %n, 10
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test2:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test2(i32 %n, i32 %i) {
+  %add = add nsw i32 10, %n
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test3:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test3(i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  store i32 %i, i32* %add.ptr1, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test4:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test4(i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
+  store i32 %i, i32* %add.ptr, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test5:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test5(i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), i32 %n
+  store i32 %i, i32* %add.ptr, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test6:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test6(i32 %n, i32 %i) {
+  %add = add nsw i32 %n, 10
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  store i32 %i, i32* %add.ptr, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test7:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test7(i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  store i32 %i, i32* %add.ptr1, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test8:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, g+40($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test8(i32 %n, i32 %i) {
+  %add = add nsw i32 10, %n
+  %add.ptr = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  store i32 %i, i32* %add.ptr, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test9:
+; CHECK-NEXT: param     i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 0{{$}}
+; CHECK-NEXT: i32.store $discard=, g-40($pop0), $0{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test9(i32 %i) {
+  store i32 %i, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 1073741814), align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test10:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.const $push2=, g-40{{$}}
+; CHECK-NEXT: i32.add   $push3=, $pop1, $pop2{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop3), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test10(i32 %n, i32 %i) {
+  %add = add nsw i32 %n, -10
+  %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test11:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.store $discard=, 40($0), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test11(i32* %p, i32 %i) {
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 10
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test11_noinbounds:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 40{{$}}
+; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test11_noinbounds(i32* %p, i32 %i) {
+  %arrayidx = getelementptr i32, i32* %p, i32 10
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test12:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test12(i32* %p, i32 %n, i32 %i) {
+  %add = add nsw i32 %n, 10
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test13:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test13(i32* %p, i32 %n, i32 %i) {
+  %add = add nsw i32 10, %n
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test14:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.store $discard=, 40($pop2), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test14(i32* %p, i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  store i32 %i, i32* %add.ptr1, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test15:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test15(i32* %p, i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
+  store i32 %i, i32* %add.ptr1, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test16:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test16(i32* %p, i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 10
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 %n
+  store i32 %i, i32* %add.ptr1, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test17:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test17(i32* %p, i32 %n, i32 %i) {
+  %add = add nsw i32 %n, 10
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
+  store i32 %i, i32* %add.ptr, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test18:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $0, $pop1{{$}}
+; CHECK-NEXT: i32.store $discard=, 40($pop2), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test18(i32* %p, i32 %n, i32 %i) {
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n
+  %add.ptr1 = getelementptr inbounds i32, i32* %add.ptr, i32 10
+  store i32 %i, i32* %add.ptr1, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test19:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, 40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test19(i32* %p, i32 %n, i32 %i) {
+  %add = add nsw i32 10, %n
+  %add.ptr = getelementptr inbounds i32, i32* %p, i32 %add
+  store i32 %i, i32* %add.ptr, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test20:
+; CHECK-NEXT: param     i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, -40{{$}}
+; CHECK-NEXT: i32.add   $push1=, $0, $pop0{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop1), $1{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test20(i32* %p, i32 %i) {
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 -10
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: store_test21:
+; CHECK-NEXT: param     i32, i32, i32{{$}}
+; CHECK-NEXT: i32.const $push0=, 2{{$}}
+; CHECK-NEXT: i32.shl   $push1=, $1, $pop0{{$}}
+; CHECK-NEXT: i32.add   $push2=, $pop1, $0{{$}}
+; CHECK-NEXT: i32.const $push3=, -40{{$}}
+; CHECK-NEXT: i32.add   $push4=, $pop2, $pop3{{$}}
+; CHECK-NEXT: i32.store $discard=, 0($pop4), $2{{$}}
+; CHECK-NEXT: return{{$}}
+define void @store_test21(i32* %p, i32 %n, i32 %i) {
+  %add = add nsw i32 %n, -10
+  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %add
+  store i32 %i, i32* %arrayidx, align 4
+  ret void
+}
Index: test/CodeGen/X86/lea-opt.ll
===================================================================
--- test/CodeGen/X86/lea-opt.ll
+++ test/CodeGen/X86/lea-opt.ll
@@ -34,12 +34,12 @@
 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
   ret void
 ; CHECK-LABEL: test1:
-; CHECK:	leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]]
-; CHECK:	movl arr1(,[[REG1]],4), {{.*}}
-; CHECK:	leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]]
-; CHECK:	subl arr1+4(,[[REG1]],4), {{.*}}
-; CHECK:	leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]]
-; CHECK:	addl arr1+8(,[[REG1]],4), {{.*}}
+; CHECK:	shlq $2, [[REG1:%[a-z]+]]
+; CHECK:	movl arr1([[REG1]],[[REG1]],2), {{.*}}
+; CHECK:	leaq arr1+4([[REG1]],[[REG1]],2), [[REG2:%[a-z]+]]
+; CHECK:	subl arr1+4([[REG1]],[[REG1]],2), {{.*}}
+; CHECK:	leaq arr1+8([[REG1]],[[REG1]],2), [[REG3:%[a-z]+]]
+; CHECK:	addl arr1+8([[REG1]],[[REG1]],2), {{.*}}
 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
@@ -74,11 +74,11 @@
 sw.epilog:                                        ; preds = %sw.bb.2, %sw.bb.1, %entry
   ret void
 ; CHECK-LABEL: test2:
-; CHECK:	leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]]
-; CHECK:	leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]]
+; CHECK:	shlq $2, [[REG1:%[a-z]+]]
+; CHECK:	leaq arr1+4([[REG1]],[[REG1]],2), [[REG2:%[a-z]+]]
 ; CHECK:	movl -4([[REG2]]), {{.*}}
 ; CHECK:	subl ([[REG2]]), {{.*}}
-; CHECK:	leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]]
+; CHECK:	leaq arr1+8([[REG1]],[[REG1]],2), [[REG3:%[a-z]+]]
 ; CHECK:	addl ([[REG3]]), {{.*}}
 ; CHECK:	movl ${{[1-4]+}}, ([[REG2]])
 ; CHECK:	movl ${{[1-4]+}}, ([[REG3]])
Index: test/CodeGen/XCore/threads.ll
===================================================================
--- test/CodeGen/XCore/threads.ll
+++ test/CodeGen/XCore/threads.ll
@@ -87,7 +87,7 @@
 ; CHECK: shl [[R0:r[0-9]]], r11, 3
 ; CHECK: ldaw [[R1:r[0-9]]], dp[tle]
 ; r0 = &tl + id*8
-; CHECK: add r0, [[R1]], [[R0]]
+; CHECK: add r0, [[R0]], [[R1]]
   ret i32* getelementptr inbounds ([2 x i32], [2 x i32]* @tle, i32 0, i32 0)
 }
 
@@ -96,7 +96,7 @@
 ; CHECK: get r11, id
 ; CHECK: shl [[R0:r[0-9]]], r11, 3
 ; CHECK: ldaw [[R1:r[0-9]]], dp[tle]
-; CHECK: add [[R2:r[0-9]]], [[R1]], [[R0]]
+; CHECK: add [[R2:r[0-9]]], [[R0]], [[R1]]
 ; CHECK: add r0, [[R2]], [[R2]]
   ret i32 add(
       i32 ptrtoint( i32* getelementptr inbounds ([2 x i32], [2 x i32]* @tle, i32 0, i32 0) to i32),