@@ -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,185 @@ bool MemOpt::optimizeGEP64(Instruction* I) const {
20912065 return Changed;
20922066}
20932067
2068+ // getConstantOffset - Return the constant offset between two memory
2069+ // locations.
2070+ bool SymbolicPointer::getConstantOffset (SymbolicPointer& Other, int64_t & Off) {
2071+ Term* DiffTerm = nullptr ;
2072+ Term* DiffOtherTerm = nullptr ;
2073+
2074+ // Find how many differences there are between the two vectors of terms.
2075+ auto findDifferences = [&](SmallVector<Term, 8 >& Terms1, SmallVector<Term, 8 >& Terms2) -> int {
2076+ int DiffCount = 0 ;
2077+ for (unsigned i = 0 , e = Terms1.size (); i != e; ++i) {
2078+ bool Found = false ;
2079+ for (unsigned j = 0 , f = Terms2.size (); !Found && j != f; ++j)
2080+ if (Terms1[i] == Terms2[j])
2081+ Found = true ;
2082+
2083+ if (!Found) {
2084+ DiffCount++;
2085+ if (DiffCount > 1 )
2086+ break ;
2087+
2088+ DiffTerm = &Terms1[i];
2089+ }
2090+ }
2091+
2092+ // If there are no differences, no need to check further.
2093+ if (DiffCount == 0 )
2094+ return DiffCount;
2095+
2096+ for (unsigned i = 0 , e = Terms2.size (); i != e; ++i) {
2097+ bool Found = false ;
2098+ for (unsigned j = 0 , f = Terms1.size (); !Found && j != f; ++j)
2099+ if (Terms2[i] == Terms1[j])
2100+ Found = true ;
2101+
2102+ if (!Found) {
2103+ DiffOtherTerm = &Terms2[i];
2104+ break ;
2105+ }
2106+ }
2107+
2108+ return DiffCount;
2109+ };
2110+
2111+ if (!BasePtr || !Other.BasePtr )
2112+ return true ;
2113+
2114+ if (BasePtr != Other.BasePtr &&
2115+ (!isa<ConstantPointerNull>(BasePtr) ||
2116+ !isa<ConstantPointerNull>(Other.BasePtr )))
2117+ return true ;
2118+
2119+ if (Terms.size () != Other.Terms .size ())
2120+ return true ;
2121+
2122+ int DiffCount = findDifferences (Terms, Other.Terms );
2123+
2124+ if (DiffCount > 1 )
2125+ return true ;
2126+
2127+ Off = Offset - Other.Offset ;
2128+
2129+ if (DiffCount == 0 )
2130+ return false ;
2131+
2132+ if (checkTerms (DiffTerm, DiffOtherTerm, Off))
2133+ return true ;
2134+
2135+ return false ;
2136+ }
2137+
2138+ // Try to match the pattern that can't be processed by the current decomposePointer algorithm.
2139+ // First chain:
2140+ // %145 = add nsw i32 %102, 1
2141+ // %146 = sub nsw i32 %145, %const_reg_dword18
2142+ //
2143+ // Second chain:
2144+ // %176 = add nsw i32 %102, 2
2145+ // %177 = sub nsw i32 %176, %const_reg_dword18
2146+ bool SymbolicPointer::checkTerms (const Term* T, const Term* OtherT, int64_t & Off) const {
2147+ bool IsPositive = true ;
2148+ size_t OpNum = 0 ;
2149+
2150+ // Check that the instructions are add or sub with nsw flag.
2151+ auto checkInstructions = [&](const BinaryOperator* Inst0, const BinaryOperator* Inst1) -> bool {
2152+ if (!Inst0 || !Inst1)
2153+ return true ;
2154+
2155+ if (Inst1->getOpcode () != Inst0->getOpcode ())
2156+ return true ;
2157+
2158+ if (Inst0->getOpcode () != Instruction::Add && Inst0->getOpcode () != Instruction::Sub)
2159+ return true ;
2160+
2161+ if (!Inst0->hasNoSignedWrap () || !Inst1->hasNoSignedWrap ())
2162+ return true ;
2163+
2164+ if (Inst0->getOperand (0 ) != Inst1->getOperand (0 ) &&
2165+ Inst0->getOperand (1 ) != Inst1->getOperand (1 ))
2166+ return true ;
2167+
2168+ if (Inst0->getOpcode () == Instruction::Sub) {
2169+ if (Inst0->getOperand (0 ) == Inst1->getOperand (0 )) {
2170+ OpNum = 1 ;
2171+ IsPositive = !IsPositive;
2172+ } else {
2173+ OpNum = 0 ;
2174+ }
2175+ } else {
2176+ if (Inst0->getOperand (1 ) == Inst1->getOperand (1 )) {
2177+ OpNum = 0 ;
2178+ } else {
2179+ OpNum = 1 ;
2180+ }
2181+ }
2182+
2183+ return false ;
2184+ };
2185+
2186+ if (!T || !OtherT)
2187+ return true ;
2188+
2189+ auto * Inst = dyn_cast<BinaryOperator>(T->Idx .getPointer ());
2190+ auto * OtherInst = dyn_cast<BinaryOperator>(OtherT->Idx .getPointer ());
2191+ if (checkInstructions (Inst, OtherInst))
2192+ return true ;
2193+
2194+ auto InstOp0 = dyn_cast<BinaryOperator>(Inst->getOperand (OpNum));
2195+ auto OtherInstOp0 = dyn_cast<BinaryOperator>(OtherInst->getOperand (OpNum));
2196+ if (checkInstructions (InstOp0, OtherInstOp0))
2197+ return true ;
2198+
2199+ auto ConstInt = dyn_cast<ConstantInt>(InstOp0->getOperand (1 ));
2200+ auto OtherConstInt = dyn_cast<ConstantInt>(OtherInstOp0->getOperand (1 ));
2201+ if (!ConstInt || !OtherConstInt)
2202+ return true ;
2203+
2204+ int64_t NewScale = T->Scale ;
2205+ int64_t NewOtherScale = OtherT->Scale ;
2206+ if (!IsPositive) {
2207+ NewScale = -NewScale;
2208+ NewOtherScale = -NewOtherScale;
2209+ }
2210+
2211+ Off += ConstInt->getSExtValue () * NewScale - OtherConstInt->getSExtValue () * NewOtherScale;
2212+ return false ;
2213+ }
2214+
2215+ // Save Term in the vector of terms.
2216+ void SymbolicPointer::saveTerm (Value* Src, int64_t IndexScale, uint64_t Scale, int64_t IndexOffset, ExtensionKind Extension, unsigned int ptrSize) {;
2217+ this ->Offset += IndexOffset * Scale;
2218+ Scale *= IndexScale;
2219+
2220+ SymbolicIndex Idx (Src, Extension);
2221+
2222+ // If we already had an occurrence of this index variable, merge this
2223+ // scale into it. For example, we want to handle:
2224+ // A[x][x] -> x*16 + x*4 -> x*20
2225+ // This also ensures that 'x' only appears in the index list once.
2226+ for (unsigned i = 0 , e = this ->Terms .size (); i != e; ++i) {
2227+ if (this ->Terms [i].Idx == Idx) {
2228+ Scale += this ->Terms [i].Scale ;
2229+ this ->Terms .erase (this ->Terms .begin () + i);
2230+ break ;
2231+ }
2232+ }
2233+
2234+ // Make sure that we have a scale that makes sense for this target's
2235+ // pointer size.
2236+ if (unsigned ShiftBits = 64 - ptrSize) {
2237+ Scale <<= ShiftBits;
2238+ Scale = (int64_t )Scale >> ShiftBits;
2239+ }
2240+
2241+ if (Scale) {
2242+ Term Entry = { Idx, int64_t (Scale) };
2243+ this ->Terms .push_back (Entry);
2244+ }
2245+ }
2246+
20942247Value*
20952248SymbolicPointer::getLinearExpression (Value* V, APInt& Scale, APInt& Offset,
20962249 ExtensionKind& Extension, unsigned Depth,
@@ -2247,34 +2400,7 @@ SymbolicPointer::decomposePointer(const Value* Ptr, SymbolicPointer& SymPtr,
22472400 APInt IndexScale (Width, 0 ), IndexOffset (Width, 0 );
22482401 Src = getLinearExpression (Src, IndexScale, IndexOffset, Extension,
22492402 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- }
2403+ SymPtr.saveTerm (Src, IndexScale.getSExtValue (), Scale, IndexOffset.getSExtValue (), Extension, ptrSize);
22782404
22792405 Ptr = BasePtr;
22802406 }
@@ -2357,34 +2483,7 @@ SymbolicPointer::decomposePointer(const Value* Ptr, SymbolicPointer& SymPtr,
23572483
23582484 // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale.
23592485 // 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- }
2486+ SymPtr.saveTerm (new_Ind, IndexScale.getSExtValue (), Scale, IndexOffset.getSExtValue (), Extension, ptrSize);
23882487 }
23892488 }
23902489
0 commit comments