@@ -412,45 +412,19 @@ namespace {
412412 int64_t Offset;
413413 SmallVector<Term, 8 > Terms;
414414
415- // getConstantOffset - Return the constant offset between two memory
416- // locations.
417- bool getConstantOffset (const SymbolicPointer& Other, int64_t & Off) {
418- if (!BasePtr || !Other.BasePtr )
419- return true ;
420-
421- if (BasePtr != Other.BasePtr &&
422- (!isa<ConstantPointerNull>(BasePtr) ||
423- !isa<ConstantPointerNull>(Other.BasePtr )))
424- return true ;
425-
426- if (Terms.size () != Other.Terms .size ())
427- return true ;
428-
429- // Check each term has occurrence in Other. Since, they have the same
430- // number of terms, it's safe to say they are equal if all terms are
431- // found in Other.
432- // TODO: Replace this check with a non-quadratic one.
433- for (unsigned i = 0 , e = Terms.size (); i != e; ++i) {
434- bool Found = false ;
435- for (unsigned j = 0 , f = Other.Terms .size (); !Found && j != f; ++j) {
436- if (Terms[i] == Other.Terms [j])
437- Found = true ;
438- }
439- if (!Found)
440- return true ;
441- }
442-
443- Off = Offset - Other.Offset ;
444- return false ;
445- }
446-
415+ bool getConstantOffset (SymbolicPointer& Other, int64_t & Off);
447416 static Value* getLinearExpression (Value* Val, APInt& Scale, APInt& Offset,
448417 ExtensionKind& Extension, unsigned Depth,
449418 const DataLayout* DL);
450419 static bool decomposePointer (const Value* Ptr, SymbolicPointer& SymPtr,
451420 CodeGenContext* DL);
452421
453422 static const unsigned MaxLookupSearchDepth = 6 ;
423+
424+ private:
425+ void saveTerm (Value* Src, int64_t IndexScale, uint64_t Scale, int64_t IndexOffset,
426+ ExtensionKind Extension, unsigned int ptrSize);
427+ bool checkTerms (const Term* T, const Term* OtherT, int64_t & Off) const ;
454428 };
455429}
456430
@@ -2091,6 +2065,183 @@ bool MemOpt::optimizeGEP64(Instruction* I) const {
20912065 return Changed;
20922066}
20932067
2068+ bool SymbolicPointer::getConstantOffset (SymbolicPointer& Other, int64_t & Off) {
2069+ Term* DiffTerm = nullptr ;
2070+ Term* DiffOtherTerm = nullptr ;
2071+
2072+ // Find how many differences there are between the two vectors of terms.
2073+ auto findDifferences = [&](SmallVector<Term, 8 >& Terms1, SmallVector<Term, 8 >& Terms2) -> int {
2074+ int DiffCount = 0 ;
2075+ for (unsigned i = 0 , e = Terms1.size (); i != e; ++i) {
2076+ bool Found = false ;
2077+ for (unsigned j = 0 , f = Terms2.size (); !Found && j != f; ++j)
2078+ if (Terms1[i] == Terms2[j])
2079+ Found = true ;
2080+
2081+ if (!Found) {
2082+ DiffCount++;
2083+ if (DiffCount > 1 )
2084+ break ;
2085+
2086+ DiffTerm = &Terms1[i];
2087+ }
2088+ }
2089+
2090+ // If there are no differences, no need to check further.
2091+ if (DiffCount == 0 )
2092+ return DiffCount;
2093+
2094+ for (unsigned i = 0 , e = Terms2.size (); i != e; ++i) {
2095+ bool Found = false ;
2096+ for (unsigned j = 0 , f = Terms1.size (); !Found && j != f; ++j)
2097+ if (Terms2[i] == Terms1[j])
2098+ Found = true ;
2099+
2100+ if (!Found) {
2101+ DiffOtherTerm = &Terms2[i];
2102+ break ;
2103+ }
2104+ }
2105+
2106+ return DiffCount;
2107+ };
2108+
2109+ if (!BasePtr || !Other.BasePtr )
2110+ return true ;
2111+
2112+ if (BasePtr != Other.BasePtr &&
2113+ (!isa<ConstantPointerNull>(BasePtr) ||
2114+ !isa<ConstantPointerNull>(Other.BasePtr )))
2115+ return true ;
2116+
2117+ if (Terms.size () != Other.Terms .size ())
2118+ return true ;
2119+
2120+ int DiffCount = findDifferences (Terms, Other.Terms );
2121+
2122+ if (DiffCount == 0 ) {
2123+ Off = Offset - Other.Offset ;
2124+ return false ;
2125+ }
2126+
2127+ if (DiffCount > 1 )
2128+ return true ;
2129+
2130+ if (checkTerms (DiffTerm, DiffOtherTerm, Off))
2131+ return true ;
2132+
2133+ return false ;
2134+ }
2135+
2136+ // Try to match the pattern that can't be processed by the current decomposePointer algorithm.
2137+ // First chain:
2138+ // %145 = add nsw i32 %102, 1
2139+ // %146 = sub nsw i32 %145, %const_reg_dword18
2140+ //
2141+ // Second chain:
2142+ // %176 = add nsw i32 %102, 2
2143+ // %177 = sub nsw i32 %176, %const_reg_dword18
2144+ bool SymbolicPointer::checkTerms (const Term* T, const Term* OtherT, int64_t & Off) const {
2145+ bool IsPositive = true ;
2146+ size_t OpNum = 0 ;
2147+
2148+ // Check that the instructions are add or sub with nsw flag.
2149+ auto checkInstructions = [&](const BinaryOperator* Inst0, const BinaryOperator* Inst1) -> bool {
2150+ if (!Inst0 || !Inst1)
2151+ return true ;
2152+
2153+ if (Inst1->getOpcode () != Inst0->getOpcode ())
2154+ return true ;
2155+
2156+ if (Inst0->getOpcode () != Instruction::Add && Inst0->getOpcode () != Instruction::Sub)
2157+ return true ;
2158+
2159+ if (!Inst0->hasNoSignedWrap () || !Inst1->hasNoSignedWrap ())
2160+ return true ;
2161+
2162+ if (Inst0->getOperand (0 ) != Inst1->getOperand (0 ) &&
2163+ Inst0->getOperand (1 ) != Inst1->getOperand (1 ))
2164+ return true ;
2165+
2166+ if (Inst0->getOpcode () == Instruction::Sub) {
2167+ if (Inst0->getOperand (0 ) == Inst1->getOperand (0 )) {
2168+ OpNum = 1 ;
2169+ IsPositive = !IsPositive;
2170+ } else {
2171+ OpNum = 0 ;
2172+ }
2173+ } else {
2174+ if (Inst0->getOperand (1 ) == Inst1->getOperand (1 )) {
2175+ OpNum = 0 ;
2176+ } else {
2177+ OpNum = 1 ;
2178+ }
2179+ }
2180+
2181+ return false ;
2182+ };
2183+
2184+ if (!T || !OtherT)
2185+ return true ;
2186+
2187+ auto * Inst = dyn_cast<BinaryOperator>(T->Idx .getPointer ());
2188+ auto * OtherInst = dyn_cast<BinaryOperator>(OtherT->Idx .getPointer ());
2189+ if (checkInstructions (Inst, OtherInst))
2190+ return true ;
2191+
2192+ auto InstOp0 = dyn_cast<BinaryOperator>(Inst->getOperand (OpNum));
2193+ auto OtherInstOp0 = dyn_cast<BinaryOperator>(OtherInst->getOperand (OpNum));
2194+ if (checkInstructions (InstOp0, OtherInstOp0))
2195+ return true ;
2196+
2197+ auto ConstInt = dyn_cast<ConstantInt>(InstOp0->getOperand (1 ));
2198+ auto OtherConstInt = dyn_cast<ConstantInt>(OtherInstOp0->getOperand (1 ));
2199+ if (!ConstInt || !OtherConstInt)
2200+ return true ;
2201+
2202+ int64_t NewScale = T->Scale ;
2203+ int64_t NewOtherScale = OtherT->Scale ;
2204+ if (!IsPositive) {
2205+ NewScale = -NewScale;
2206+ NewOtherScale = -NewOtherScale;
2207+ }
2208+
2209+ Off = ConstInt->getSExtValue () * NewScale - OtherConstInt->getSExtValue () * NewOtherScale;
2210+ return false ;
2211+ }
2212+
2213+ // Save Term in the vector of terms.
2214+ void SymbolicPointer::saveTerm (Value* Src, int64_t IndexScale, uint64_t Scale, int64_t IndexOffset, ExtensionKind Extension, unsigned int ptrSize) {;
2215+ this ->Offset += IndexOffset * Scale;
2216+ Scale *= IndexScale;
2217+
2218+ SymbolicIndex Idx (Src, Extension);
2219+
2220+ // If we already had an occurrence of this index variable, merge this
2221+ // scale into it. For example, we want to handle:
2222+ // A[x][x] -> x*16 + x*4 -> x*20
2223+ // This also ensures that 'x' only appears in the index list once.
2224+ for (unsigned i = 0 , e = this ->Terms .size (); i != e; ++i) {
2225+ if (this ->Terms [i].Idx == Idx) {
2226+ Scale += this ->Terms [i].Scale ;
2227+ this ->Terms .erase (this ->Terms .begin () + i);
2228+ break ;
2229+ }
2230+ }
2231+
2232+ // Make sure that we have a scale that makes sense for this target's
2233+ // pointer size.
2234+ if (unsigned ShiftBits = 64 - ptrSize) {
2235+ Scale <<= ShiftBits;
2236+ Scale = (int64_t )Scale >> ShiftBits;
2237+ }
2238+
2239+ if (Scale) {
2240+ Term Entry = { Idx, int64_t (Scale) };
2241+ this ->Terms .push_back (Entry);
2242+ }
2243+ }
2244+
20942245Value*
20952246SymbolicPointer::getLinearExpression (Value* V, APInt& Scale, APInt& Offset,
20962247 ExtensionKind& Extension, unsigned Depth,
@@ -2247,34 +2398,7 @@ SymbolicPointer::decomposePointer(const Value* Ptr, SymbolicPointer& SymPtr,
22472398 APInt IndexScale (Width, 0 ), IndexOffset (Width, 0 );
22482399 Src = getLinearExpression (Src, IndexScale, IndexOffset, Extension,
22492400 0U , DL);
2250- SymPtr.Offset += IndexOffset.getSExtValue () * Scale;
2251- Scale *= IndexScale.getSExtValue ();
2252-
2253- SymbolicIndex Idx (Src, Extension);
2254-
2255- // If we already had an occurrence of this index variable, merge this
2256- // scale into it. For example, we want to handle:
2257- // A[x][x] -> x*16 + x*4 -> x*20
2258- // This also ensures that 'x' only appears in the index list once.
2259- for (unsigned i = 0 , e = SymPtr.Terms .size (); i != e; ++i) {
2260- if (SymPtr.Terms [i].Idx == Idx) {
2261- Scale += SymPtr.Terms [i].Scale ;
2262- SymPtr.Terms .erase (SymPtr.Terms .begin () + i);
2263- break ;
2264- }
2265- }
2266-
2267- // Make sure that we have a scale that makes sense for this target's
2268- // pointer size.
2269- if (unsigned ShiftBits = 64 - ptrSize) {
2270- Scale <<= ShiftBits;
2271- Scale = (int64_t )Scale >> ShiftBits;
2272- }
2273-
2274- if (Scale) {
2275- Term Entry = { Idx, int64_t (Scale) };
2276- SymPtr.Terms .push_back (Entry);
2277- }
2401+ SymPtr.saveTerm (Src, IndexScale.getSExtValue (), Scale, IndexOffset.getSExtValue (), Extension, ptrSize);
22782402
22792403 Ptr = BasePtr;
22802404 }
@@ -2357,34 +2481,7 @@ SymbolicPointer::decomposePointer(const Value* Ptr, SymbolicPointer& SymPtr,
23572481
23582482 // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale.
23592483 // This gives us an aggregate computation of (C1*Scale)*V + C2*Scale.
2360- SymPtr.Offset += IndexOffset.getSExtValue () * Scale;
2361- Scale *= IndexScale.getSExtValue ();
2362-
2363- SymbolicIndex Idx (new_Ind, Extension);
2364-
2365- // If we already had an occurrence of this index variable, merge this
2366- // scale into it. For example, we want to handle:
2367- // A[x][x] -> x*16 + x*4 -> x*20
2368- // This also ensures that 'x' only appears in the index list once.
2369- for (unsigned i = 0 , e = SymPtr.Terms .size (); i != e; ++i) {
2370- if (SymPtr.Terms [i].Idx == Idx) {
2371- Scale += SymPtr.Terms [i].Scale ;
2372- SymPtr.Terms .erase (SymPtr.Terms .begin () + i);
2373- break ;
2374- }
2375- }
2376-
2377- // Make sure that we have a scale that makes sense for this target's
2378- // pointer size.
2379- if (unsigned ShiftBits = 64 - ptrSize) {
2380- Scale <<= ShiftBits;
2381- Scale = (int64_t )Scale >> ShiftBits;
2382- }
2383-
2384- if (Scale) {
2385- Term Entry = { Idx, int64_t (Scale) };
2386- SymPtr.Terms .push_back (Entry);
2387- }
2484+ SymPtr.saveTerm (new_Ind, IndexScale.getSExtValue (), Scale, IndexOffset.getSExtValue (), Extension, ptrSize);
23882485 }
23892486 }
23902487
0 commit comments