@@ -1864,177 +1864,52 @@ void at::deleteAll(Function *F) {
18641864 DVR->eraseFromParent ();
18651865}
18661866
1867- // / Get the FragmentInfo for the variable if it exists, otherwise return a
1868- // / FragmentInfo that covers the entire variable if the variable size is
1869- // / known, otherwise return a zero-sized fragment.
1870- static DIExpression::FragmentInfo
1871- getFragmentOrEntireVariable (const DbgVariableRecord *DVR) {
1872- DIExpression::FragmentInfo VariableSlice (0 , 0 );
1873- // Get the fragment or variable size, or zero.
1874- if (auto Sz = DVR->getFragmentSizeInBits ())
1875- VariableSlice.SizeInBits = *Sz;
1876- if (auto Frag = DVR->getExpression ()->getFragmentInfo ())
1877- VariableSlice.OffsetInBits = Frag->OffsetInBits ;
1878- return VariableSlice;
1879- }
1880-
1881- static DIExpression::FragmentInfo
1882- getFragmentOrEntireVariable (const DbgVariableIntrinsic *DVI) {
1883- DIExpression::FragmentInfo VariableSlice (0 , 0 );
1884- // Get the fragment or variable size, or zero.
1885- if (auto Sz = DVI->getFragmentSizeInBits ())
1886- VariableSlice.SizeInBits = *Sz;
1887- if (auto Frag = DVI->getExpression ()->getFragmentInfo ())
1888- VariableSlice.OffsetInBits = Frag->OffsetInBits ;
1889- return VariableSlice;
1890- }
1867+ // / FIXME: Remove this wrapper function and call
1868+ // / DIExpression::calculateFragmentIntersect directly.
18911869template <typename T>
18921870bool calculateFragmentIntersectImpl (
18931871 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits,
18941872 uint64_t SliceSizeInBits, const T *AssignRecord,
18951873 std::optional<DIExpression::FragmentInfo> &Result) {
1896- // There are multiple offsets at play in this function, so let's break it
1897- // down. Starting with how variables may be stored in allocas:
1898- //
1899- // 1 Simplest case: variable is alloca sized and starts at offset 0.
1900- // 2 Variable is larger than the alloca: the alloca holds just a part of it.
1901- // 3 Variable is smaller than the alloca: the alloca may hold multiple
1902- // variables.
1903- //
1904- // Imagine we have a store to the entire alloca. In case (3) the store
1905- // affects bits outside of the bounds of each variable. In case (2), where
1906- // the alloca holds the Xth bit to the Yth bit of a variable, the
1907- // zero-offset store doesn't represent an assignment at offset zero to the
1908- // variable. It is an assignment to offset X.
1909- //
1910- // # Example 1
1911- // Obviously, not all stores are alloca-sized and have zero offset. Imagine
1912- // the lower 32 bits of this store are dead and are going to be DSEd:
1913- //
1914- // store i64 %v, ptr %dest, !DIAssignID !1
1915- // dbg.assign(..., !DIExpression(fragment, 128, 32), !1, %dest,
1916- // !DIExpression(DW_OP_plus_uconst, 4))
1917- //
1918- // Goal: Given our dead bits at offset:0 size:32 for the store, determine the
1919- // part of the variable, which fits in the fragment expressed by the
1920- // dbg.assign, that has been killed, if any.
1921- //
1922- // calculateFragmentIntersect(..., SliceOffsetInBits=0,
1923- // SliceSizeInBits=32, Dest=%dest, Assign=dbg.assign)
1924- //
1925- // Drawing the store (s) in memory followed by the shortened version ($),
1926- // then the dbg.assign (d), with the fragment information on a separate scale
1927- // underneath:
1928- //
1929- // Memory
1930- // offset
1931- // from
1932- // dest 0 63
1933- // | |
1934- // s[######] - Original stores 64 bits to Dest.
1935- // $----[##] - DSE says the lower 32 bits are dead, to be removed.
1936- // d [##] - Assign's address-modifying expression adds 4 bytes to
1937- // dest.
1938- // Variable | |
1939- // Fragment 128|
1940- // Offsets 159
1941- //
1942- // The answer is achieved in a few steps:
1943- // 1. Add the fragment offset to the store offset:
1944- // SliceOffsetInBits:0 + VarFrag.OffsetInBits:128 = 128
1945- //
1946- // 2. Subtract the address-modifying expression offset plus difference
1947- // between d.address and dest:
1948- // 128 - (expression_offset:32 + (d.address - dest):0) = 96
1949- //
1950- // 3. That offset along with the store size (32) represents the bits of the
1951- // variable that'd be affected by the store. Call it SliceOfVariable.
1952- // Intersect that with Assign's fragment info:
1953- // SliceOfVariable ∩ Assign_fragment = none
1954- //
1955- // In this case: none of the dead bits of the store affect Assign.
1956- //
1957- // # Example 2
1958- // Similar example with the same goal. This time the upper 16 bits
1959- // of the store are going to be DSE'd.
1960- //
1961- // store i64 %v, ptr %dest, !DIAssignID !1
1962- // dbg.assign(..., !DIExpression(fragment, 128, 32), !1, %dest,
1963- // !DIExpression(DW_OP_plus_uconst, 4))
1964- //
1965- // calculateFragmentIntersect(..., SliceOffsetInBits=48,
1966- // SliceSizeInBits=16, Dest=%dest, Assign=dbg.assign)
1967- //
1968- // Memory
1969- // offset
1970- // from
1971- // dest 0 63
1972- // | |
1973- // s[######] - Original stores 64 bits to Dest.
1974- // $[####]-- - DSE says the upper 16 bits are dead, to be removed.
1975- // d [##] - Assign's address-modifying expression adds 4 bytes to
1976- // dest.
1977- // Variable | |
1978- // Fragment 128|
1979- // Offsets 159
1980- //
1981- // Using the same steps in the first example:
1982- // 1. SliceOffsetInBits:48 + VarFrag.OffsetInBits:128 = 176
1983- // 2. 176 - (expression_offset:32 + (d.address - dest):0) = 144
1984- // 3. SliceOfVariable offset = 144, size = 16:
1985- // SliceOfVariable ∩ Assign_fragment = (offset: 144, size: 16)
1986- // SliceOfVariable tells us the bits of the variable described by Assign that
1987- // are affected by the DSE.
1874+ // No overlap if this DbgRecord describes a killed location.
19881875 if (AssignRecord->isKillAddress ())
19891876 return false ;
19901877
1991- DIExpression::FragmentInfo VarFrag =
1992- getFragmentOrEntireVariable (AssignRecord);
1993- if (VarFrag.SizeInBits == 0 )
1994- return false ; // Variable size is unknown.
1995-
1996- // Calculate the difference between Dest and the dbg.assign address +
1997- // address-modifying expression.
1998- int64_t PointerOffsetInBits;
1878+ int64_t AddrOffsetInBits;
19991879 {
2000- auto DestOffsetInBytes =
2001- AssignRecord->getAddress ()->getPointerOffsetFrom (Dest, DL);
2002- if (!DestOffsetInBytes)
2003- return false ; // Can't calculate difference in addresses.
2004-
2005- int64_t ExprOffsetInBytes;
2006- if (!AssignRecord->getAddressExpression ()->extractIfOffset (
2007- ExprOffsetInBytes))
1880+ int64_t AddrOffsetInBytes;
1881+ SmallVector<uint64_t > PostOffsetOps; // < Unused.
1882+ // Bail if we can't find a constant offset (or none) in the expression.
1883+ if (!AssignRecord->getAddressExpression ()->extractLeadingOffset (
1884+ AddrOffsetInBytes, PostOffsetOps))
20081885 return false ;
2009-
2010- int64_t PointerOffsetInBytes = *DestOffsetInBytes + ExprOffsetInBytes;
2011- PointerOffsetInBits = PointerOffsetInBytes * 8 ;
1886+ AddrOffsetInBits = AddrOffsetInBytes * 8 ;
20121887 }
20131888
2014- // Adjust the slice offset so that we go from describing the a slice
2015- // of memory to a slice of the variable.
2016- int64_t NewOffsetInBits =
2017- SliceOffsetInBits + VarFrag.OffsetInBits - PointerOffsetInBits;
2018- if (NewOffsetInBits < 0 )
2019- return false ; // Fragment offsets can only be positive.
2020- DIExpression::FragmentInfo SliceOfVariable (SliceSizeInBits, NewOffsetInBits);
2021- // Intersect the variable slice with AssignRecord's fragment to trim it down
2022- // to size.
2023- DIExpression::FragmentInfo TrimmedSliceOfVariable =
2024- DIExpression::FragmentInfo::intersect (SliceOfVariable, VarFrag);
2025- if (TrimmedSliceOfVariable == VarFrag)
2026- Result = std::nullopt ;
2027- else
2028- Result = TrimmedSliceOfVariable;
2029- return true ;
1889+ Value *Addr = AssignRecord->getAddress ();
1890+ // FIXME: It may not always be zero.
1891+ int64_t BitExtractOffsetInBits = 0 ;
1892+ DIExpression::FragmentInfo VarFrag =
1893+ AssignRecord->getFragmentOrEntireVariable ();
1894+
1895+ int64_t OffsetFromLocationInBits; // < Unused.
1896+ return DIExpression::calculateFragmentIntersect (
1897+ DL, Dest, SliceOffsetInBits, SliceSizeInBits, Addr, AddrOffsetInBits,
1898+ BitExtractOffsetInBits, VarFrag, Result, OffsetFromLocationInBits);
20301899}
1900+
1901+ // / FIXME: Remove this wrapper function and call
1902+ // / DIExpression::calculateFragmentIntersect directly.
20311903bool at::calculateFragmentIntersect (
20321904 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits,
20331905 uint64_t SliceSizeInBits, const DbgAssignIntrinsic *DbgAssign,
20341906 std::optional<DIExpression::FragmentInfo> &Result) {
20351907 return calculateFragmentIntersectImpl (DL, Dest, SliceOffsetInBits,
20361908 SliceSizeInBits, DbgAssign, Result);
20371909}
1910+
1911+ // / FIXME: Remove this wrapper function and call
1912+ // / DIExpression::calculateFragmentIntersect directly.
20381913bool at::calculateFragmentIntersect (
20391914 const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits,
20401915 uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign,
0 commit comments