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(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(N)) + if (TLI.isOffsetFoldingLegal(GA) && + GA->getOpcode() == ISD::GlobalAddress) + 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(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(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 &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 @@ -3272,6 +3272,26 @@ return getConstant(Folded.first, DL, VT); } +SDValue SelectionDAG::FoldSymbolOffset(unsigned Opcode, EVT VT, + const GlobalAddressSDNode *GA, + const SDNode *N2) { + if (!TLI->isOffsetFoldingLegal(GA)) + return SDValue(); + if (GA->getOpcode() != ISD::GlobalAddress) + return SDValue(); + const ConstantSDNode *Cst2 = dyn_cast(N2); + if (!Cst2) + return SDValue(); + uint64_t Offset = Cst2->getSExtValue(); + switch (Opcode) { + case ISD::ADD: break; + case ISD::SUB: Offset = -Offset; break; + default: return SDValue(); + } + return getGlobalAddress(GA->getGlobal(), SDLoc(Cst2), VT, + GA->getOffset() + 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 @@ -3298,6 +3318,12 @@ } } + // fold (add Sym, c) -> Sym+c + if (GlobalAddressSDNode *GA = dyn_cast(Cst1)) + return FoldSymbolOffset(Opcode, VT, GA, Cst2); + if (GlobalAddressSDNode *GA = dyn_cast(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(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),