[llvm] r258296 - [SelectionDAG] Fold more offsets into GlobalAddresses

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 21 17:31:13 PST 2016


I reverted both changes in r258465. You can reproduce the issue with the
attached file by running llc on it and looking at the hex constants stored
to the stack. It should be all 0x61 bytes and no 0x41 bytes, but with your
patch we get some 41's.

On Thu, Jan 21, 2016 at 5:00 PM, Reid Kleckner <rnk at google.com> wrote:

> This change broke the following small program on Windows:
>
> #include <string>
> #include <iostream>
> static const char kData[] = "asdf jkl;";
> int main() {
>   std::string s(kData + 3, sizeof(kData) - 3);
>   std::cout << s << '\n';
> }
>
> It should print "f jkl;", but with this patch (including the fix in
> r258366), it prints "asdf jkl;". Essentially, the +3 offset from kData got
> folded away without actually accounting for it.
>
> I'll get a better reduction soon, but I want to revert for now since this
> is close to end of day pacific time.
>
> On Tue, Jan 19, 2016 at 11:03 PM, Dan Gohman via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: djg
>> Date: Wed Jan 20 01:03:08 2016
>> New Revision: 258296
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=258296&view=rev
>> Log:
>> [SelectionDAG] Fold more offsets into GlobalAddresses
>>
>> SelectionDAG previously missed opportunities to fold constants into
>> GlobalAddresses in several areas. For example, given `(add (add GA, c1),
>> y)`, it
>> would often reassociate to `(add (add GA, y), c1)`, missing the
>> opportunity to
>> create `(add GA+c, y)`. This isn't often visible on targets such as X86
>> which
>> effectively reassociate adds in their complex address-mode folding logic,
>> however it is currently visible on WebAssembly since it currently has very
>> simple address mode folding code that doesn't reassociate anything.
>>
>> This patch fixes this by making SelectionDAG fold offsets into
>> GlobalAddresses
>> at the same times that it folds constants together, so that it doesn't
>> miss any
>> opportunities to perform such folding.
>>
>> Differential Revision: http://reviews.llvm.org/D16090
>>
>> Added:
>>     llvm/trunk/test/CodeGen/WebAssembly/address-offsets.ll
>> Modified:
>>     llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
>>     llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
>>     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
>>     llvm/trunk/test/CodeGen/X86/lea-opt.ll
>>     llvm/trunk/test/CodeGen/XCore/threads.ll
>>
>> Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=258296&r1=258295&r2=258296&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
>> +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Wed Jan 20 01:03:08
>> 2016
>> @@ -1156,6 +1156,10 @@ public:
>>    /// 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);
>>
>> @@ -1267,6 +1271,9 @@ public:
>>
>>    unsigned getEVTAlignment(EVT MemoryVT) const;
>>
>> +  /// Test whether the given value is a constant int or similar node.
>> +  SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N);
>> +
>>  private:
>>    void InsertNode(SDNode *N);
>>    bool RemoveNodeFromCSEMaps(SDNode *N);
>>
>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=258296&r1=258295&r2=258296&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Jan 20
>> 01:03:08 2016
>> @@ -390,6 +390,9 @@ namespace {
>>      /// consecutive chains.
>>      bool findBetterNeighborChains(StoreSDNode *St);
>>
>> +    /// 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 {
>> @@ -763,16 +766,6 @@ static bool isConstantSplatVector(SDNode
>>            EltVT.getSizeInBits() >= SplatBitSize);
>>  }
>>
>> -// \brief Returns the SDNode if it is a constant integer BuildVector
>> -// or constant integer.
>> -static SDNode *isConstantIntBuildVectorOrConstantInt(SDValue N) {
>> -  if (isa<ConstantSDNode>(N))
>> -    return N.getNode();
>> -  if (ISD::isBuildVectorOfConstantSDNodes(N.getNode()))
>> -    return N.getNode();
>> -  return nullptr;
>> -}
>> -
>>  // \brief Returns the SDNode if it is a constant float BuildVector
>>  // or constant float.
>>  static SDNode *isConstantFPBuildVectorOrConstantFP(SDValue N) {
>> @@ -825,8 +818,8 @@ SDValue DAGCombiner::ReassociateOps(unsi
>>                                      SDValue N0, SDValue N1) {
>>    EVT VT = N0.getValueType();
>>    if (N0.getOpcode() == Opc) {
>> -    if (SDNode *L =
>> isConstantIntBuildVectorOrConstantInt(N0.getOperand(1))) {
>> -      if (SDNode *R = isConstantIntBuildVectorOrConstantInt(N1)) {
>> +    if (SDNode *L =
>> DAG.isConstantIntBuildVectorOrConstantInt(N0.getOperand(1))) {
>> +      if (SDNode *R = DAG.isConstantIntBuildVectorOrConstantInt(N1)) {
>>          // reassoc. (op (op x, c1), c2) -> (op x, (op c1, c2))
>>          if (SDValue OpNode = DAG.FoldConstantArithmetic(Opc, DL, VT, L,
>> R))
>>            return DAG.getNode(Opc, DL, VT, N0.getOperand(0), OpNode);
>> @@ -845,8 +838,8 @@ SDValue DAGCombiner::ReassociateOps(unsi
>>    }
>>
>>    if (N1.getOpcode() == Opc) {
>> -    if (SDNode *R =
>> isConstantIntBuildVectorOrConstantInt(N1.getOperand(1))) {
>> -      if (SDNode *L = isConstantIntBuildVectorOrConstantInt(N0)) {
>> +    if (SDNode *R =
>> DAG.isConstantIntBuildVectorOrConstantInt(N1.getOperand(1))) {
>> +      if (SDNode *L = DAG.isConstantIntBuildVectorOrConstantInt(N0)) {
>>          // reassoc. (op c2, (op x, c1)) -> (op x, (op c1, c2))
>>          if (SDValue OpNode = DAG.FoldConstantArithmetic(Opc, DL, VT, R,
>> L))
>>            return DAG.getNode(Opc, DL, VT, N1.getOperand(0), OpNode);
>> @@ -1657,34 +1650,28 @@ SDValue DAGCombiner::visitADD(SDNode *N)
>>      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 (DAG.isConstantIntBuildVectorOrConstantInt(N0)) {
>> +    // canonicalize constant to RHS
>> +    if (!DAG.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 +1866,14 @@ SDValue DAGCombiner::visitSUB(SDNode *N)
>>    // 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 (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>> +      DAG.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);
>> @@ -2047,8 +2037,8 @@ SDValue DAGCombiner::visitMUL(SDNode *N)
>>                                        N0.getNode(), N1.getNode());
>>
>>    // canonicalize constant to RHS (vector doesn't have to splat)
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> -     !isConstantIntBuildVectorOrConstantInt(N1))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>> +     !DAG.isConstantIntBuildVectorOrConstantInt(N1))
>>      return DAG.getNode(ISD::MUL, SDLoc(N), VT, N1, N0);
>>    // fold (mul x, 0) -> 0
>>    if (N1IsConst && ConstValue1 == 0)
>> @@ -2125,9 +2115,9 @@ SDValue DAGCombiner::visitMUL(SDNode *N)
>>    }
>>
>>    // fold (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2)
>> -  if (isConstantIntBuildVectorOrConstantInt(N1) &&
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N1) &&
>>        N0.getOpcode() == ISD::ADD &&
>> -      isConstantIntBuildVectorOrConstantInt(N0.getOperand(1)) &&
>> +      DAG.isConstantIntBuildVectorOrConstantInt(N0.getOperand(1)) &&
>>        isMulAddWithConstProfitable(N, N0, N1))
>>        return DAG.getNode(ISD::ADD, SDLoc(N), VT,
>>                           DAG.getNode(ISD::MUL, SDLoc(N0), VT,
>> @@ -2698,8 +2688,8 @@ SDValue DAGCombiner::visitIMINMAX(SDNode
>>      return DAG.FoldConstantArithmetic(N->getOpcode(), SDLoc(N), VT, N0C,
>> N1C);
>>
>>    // canonicalize constant to RHS
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> -     !isConstantIntBuildVectorOrConstantInt(N1))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>> +     !DAG.isConstantIntBuildVectorOrConstantInt(N1))
>>      return DAG.getNode(N->getOpcode(), SDLoc(N), VT, N1, N0);
>>
>>    return SDValue();
>> @@ -3045,8 +3035,8 @@ SDValue DAGCombiner::visitAND(SDNode *N)
>>    if (N0C && N1C && !N1C->isOpaque())
>>      return DAG.FoldConstantArithmetic(ISD::AND, SDLoc(N), VT, N0C, N1C);
>>    // canonicalize constant to RHS
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> -     !isConstantIntBuildVectorOrConstantInt(N1))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>> +     !DAG.isConstantIntBuildVectorOrConstantInt(N1))
>>      return DAG.getNode(ISD::AND, SDLoc(N), VT, N1, N0);
>>    // fold (and x, -1) -> x
>>    if (isAllOnesConstant(N1))
>> @@ -3760,8 +3750,8 @@ SDValue DAGCombiner::visitOR(SDNode *N)
>>    if (N0C && N1C && !N1C->isOpaque())
>>      return DAG.FoldConstantArithmetic(ISD::OR, SDLoc(N), VT, N0C, N1C);
>>    // canonicalize constant to RHS
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> -     !isConstantIntBuildVectorOrConstantInt(N1))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>> +     !DAG.isConstantIntBuildVectorOrConstantInt(N1))
>>      return DAG.getNode(ISD::OR, SDLoc(N), VT, N1, N0);
>>    // fold (or x, 0) -> x
>>    if (isNullConstant(N1))
>> @@ -3817,9 +3807,9 @@ SDValue DAGCombiner::visitOR(SDNode *N)
>>  }
>>
>>  /// 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))) {
>> +    if (DAG.isConstantIntBuildVectorOrConstantInt(Op.getOperand(1))) {
>>        Mask = Op.getOperand(1);
>>        Op = Op.getOperand(0);
>>      } else {
>> @@ -4106,8 +4096,8 @@ SDValue DAGCombiner::visitXOR(SDNode *N)
>>    if (N0C && N1C)
>>      return DAG.FoldConstantArithmetic(ISD::XOR, SDLoc(N), VT, N0C, N1C);
>>    // canonicalize constant to RHS
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> -     !isConstantIntBuildVectorOrConstantInt(N1))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>> +     !DAG.isConstantIntBuildVectorOrConstantInt(N1))
>>      return DAG.getNode(ISD::XOR, SDLoc(N), VT, N1, N0);
>>    // fold (xor x, 0) -> x
>>    if (isNullConstant(N1))
>> @@ -4916,7 +4906,7 @@ SDValue DAGCombiner::visitBSWAP(SDNode *
>>    EVT VT = N->getValueType(0);
>>
>>    // fold (bswap c1) -> c2
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::BSWAP, SDLoc(N), VT, N0);
>>    // fold (bswap (bswap x)) -> x
>>    if (N0.getOpcode() == ISD::BSWAP)
>> @@ -4929,7 +4919,7 @@ SDValue DAGCombiner::visitCTLZ(SDNode *N
>>    EVT VT = N->getValueType(0);
>>
>>    // fold (ctlz c1) -> c2
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::CTLZ, SDLoc(N), VT, N0);
>>    return SDValue();
>>  }
>> @@ -4939,7 +4929,7 @@ SDValue DAGCombiner::visitCTLZ_ZERO_UNDE
>>    EVT VT = N->getValueType(0);
>>
>>    // fold (ctlz_zero_undef c1) -> c2
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::CTLZ_ZERO_UNDEF, SDLoc(N), VT, N0);
>>    return SDValue();
>>  }
>> @@ -4949,7 +4939,7 @@ SDValue DAGCombiner::visitCTTZ(SDNode *N
>>    EVT VT = N->getValueType(0);
>>
>>    // fold (cttz c1) -> c2
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::CTTZ, SDLoc(N), VT, N0);
>>    return SDValue();
>>  }
>> @@ -4959,7 +4949,7 @@ SDValue DAGCombiner::visitCTTZ_ZERO_UNDE
>>    EVT VT = N->getValueType(0);
>>
>>    // fold (cttz_zero_undef c1) -> c2
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::CTTZ_ZERO_UNDEF, SDLoc(N), VT, N0);
>>    return SDValue();
>>  }
>> @@ -4969,7 +4959,7 @@ SDValue DAGCombiner::visitCTPOP(SDNode *
>>    EVT VT = N->getValueType(0);
>>
>>    // fold (ctpop c1) -> c2
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::CTPOP, SDLoc(N), VT, N0);
>>    return SDValue();
>>  }
>> @@ -6902,7 +6892,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND_IN
>>      return DAG.getUNDEF(VT);
>>
>>    // fold (sext_in_reg c1) -> c1
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), VT, N0, N1);
>>
>>    // If the input is already sign extended, just drop the extension.
>> @@ -7021,7 +7011,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNod
>>    if (N0.getValueType() == N->getValueType(0))
>>      return N0;
>>    // fold (truncate c1) -> c1
>> -  if (isConstantIntBuildVectorOrConstantInt(N0))
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0))
>>      return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, N0);
>>    // fold (truncate (truncate x)) -> (truncate x)
>>    if (N0.getOpcode() == ISD::TRUNCATE)
>> @@ -8868,7 +8858,7 @@ SDValue DAGCombiner::visitSINT_TO_FP(SDN
>>    EVT OpVT = N0.getValueType();
>>
>>    // fold (sint_to_fp c1) -> c1fp
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>>        // ...but only if the target supports immediate floating-point
>> values
>>        (!LegalOperations ||
>>         TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP, VT)))
>> @@ -8922,7 +8912,7 @@ SDValue DAGCombiner::visitUINT_TO_FP(SDN
>>    EVT OpVT = N0.getValueType();
>>
>>    // fold (uint_to_fp c1) -> c1fp
>> -  if (isConstantIntBuildVectorOrConstantInt(N0) &&
>> +  if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
>>        // ...but only if the target supports immediate floating-point
>> values
>>        (!LegalOperations ||
>>         TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP, VT)))
>> @@ -10940,9 +10930,23 @@ struct BaseIndexOffset {
>>    }
>>
>>    /// 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.
>> @@ -11063,7 +11067,7 @@ bool DAGCombiner::isMulAddWithConstProfi
>>        // multiply (CONST * A) after we also do the same transformation
>>        // to the "t2" instruction.
>>        if (OtherOp->getOpcode() == ISD::ADD &&
>> -          isConstantIntBuildVectorOrConstantInt(OtherOp->getOperand(1))
>> &&
>> +
>> DAG.isConstantIntBuildVectorOrConstantInt(OtherOp->getOperand(1)) &&
>>            OtherOp->getOperand(0).getNode() == MulVar)
>>          return true;
>>      }
>> @@ -11215,7 +11219,7 @@ void DAGCombiner::getStoreMergeAndAliasC
>>      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 +11257,7 @@ void DAGCombiner::getStoreMergeAndAliasC
>>          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 +11273,7 @@ void DAGCombiner::getStoreMergeAndAliasC
>>        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 +11561,7 @@ bool DAGCombiner::MergeConsecutiveStores
>>      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 +14720,7 @@ SDValue DAGCombiner::FindBetterChain(SDN
>>  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 +14746,7 @@ bool DAGCombiner::findBetterNeighborChai
>>        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))
>>
>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=258296&r1=258295&r2=258296&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Jan 20
>> 01:03:08 2016
>> @@ -3263,6 +3263,26 @@ SDValue SelectionDAG::FoldConstantArithm
>>    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 @@ SDValue SelectionDAG::FoldConstantArithm
>>      }
>>    }
>>
>> +  // 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);
>> @@ -7322,6 +7348,22 @@ bool ShuffleVectorSDNode::isSplatMask(co
>>    return true;
>>  }
>>
>> +// \brief Returns the SDNode if it is a constant integer BuildVector
>> +// or constant integer.
>> +SDNode *SelectionDAG::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;
>> +}
>> +
>>  #ifndef NDEBUG
>>  static void checkForCyclesHelper(const SDNode *N,
>>                                   SmallPtrSetImpl<const SDNode*> &Visited,
>>
>> Added: llvm/trunk/test/CodeGen/WebAssembly/address-offsets.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/address-offsets.ll?rev=258296&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/WebAssembly/address-offsets.ll (added)
>> +++ llvm/trunk/test/CodeGen/WebAssembly/address-offsets.ll Wed Jan 20
>> 01:03:08 2016
>> @@ -0,0 +1,672 @@
>> +; 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"
>> +
>> + at 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
>> +}
>>
>> Modified: llvm/trunk/test/CodeGen/X86/lea-opt.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lea-opt.ll?rev=258296&r1=258295&r2=258296&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/lea-opt.ll (original)
>> +++ llvm/trunk/test/CodeGen/X86/lea-opt.ll Wed Jan 20 01:03:08 2016
>> @@ -34,12 +34,12 @@ sw.bb.2:
>>  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.bb.2:
>>  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]])
>>
>> Modified: llvm/trunk/test/CodeGen/XCore/threads.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/XCore/threads.ll?rev=258296&r1=258295&r2=258296&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/XCore/threads.ll (original)
>> +++ llvm/trunk/test/CodeGen/XCore/threads.ll Wed Jan 20 01:03:08 2016
>> @@ -87,7 +87,7 @@ define i32* @f_tle() {
>>  ; 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 @@ define i32 @f_tlExpr () {
>>  ; 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),
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160121/260db5d7/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: t.ll
Type: application/octet-stream
Size: 2057 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160121/260db5d7/attachment-0001.obj>


More information about the llvm-commits mailing list