diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-12-17 05:50:33 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-12-17 05:50:33 +0000 |
commit | 17304b3489b7b8ea06dd4df237f15a381ae181ce (patch) | |
tree | 00d295e407f5cd2d69878a0995c7d9b8dd54422a /lib | |
parent | b87422778c4e7b828e6e846b81fd77509439c622 (diff) |
MC/Expr: Implemnt more aggressive folding during symbol evaluation using
IsSymbolRefDifferenceFullyResolved(). For example, we will now fold away
something like:
--
_a:
...
L0:
...
L1:
...
.long (L1 - L0) / 2
--
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122043 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/MC/MCExpr.cpp | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 4465104bfe..41feaa8375 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -271,6 +271,25 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout, return true; } +/// \brief Helper method for \see EvaluateSymbolAdd(). +static void AttemptToFoldSymbolOffsetDifference(const MCAsmLayout *Layout, + const MCSymbolRefExpr *&A, + const MCSymbolRefExpr *&B, + int64_t &Addend) { + const MCAssembler &Asm = Layout->getAssembler(); + + if (A && B && + Asm.getWriter().IsSymbolRefDifferenceFullyResolved(Asm, A, B)) { + // Eagerly evaluate. + Addend += (Layout->getSymbolOffset(&Asm.getSymbolData(A->getSymbol())) - + Layout->getSymbolOffset(&Asm.getSymbolData(B->getSymbol()))); + + // Clear the symbol expr pointers to indicate we have folded these + // operands. + A = B = 0; + } +} + /// \brief Evaluate the result of an add between (conceptually) two MCValues. /// /// This routine conceptually attempts to construct an MCValue: @@ -300,20 +319,37 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout, // Fold the result constant immediately. int64_t Result_Cst = LHS_Cst + RHS_Cst; + // If we have a layout, we can fold resolved differences. + if (Layout) { + // First, fold out any differences which are fully resolved. By + // reassociating terms in + // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). + // we have the four possible differences: + // (LHS_A - LHS_B), + // (LHS_A - RHS_B), + // (RHS_A - LHS_B), + // (RHS_A - RHS_B). + // Since we are attempting to be as aggresive as possible about folding, we + // attempt to evaluate each possible alternative. + AttemptToFoldSymbolOffsetDifference(Layout, LHS_A, LHS_B, Result_Cst); + AttemptToFoldSymbolOffsetDifference(Layout, LHS_A, RHS_B, Result_Cst); + AttemptToFoldSymbolOffsetDifference(Layout, RHS_A, LHS_B, Result_Cst); + AttemptToFoldSymbolOffsetDifference(Layout, RHS_A, RHS_B, Result_Cst); + } + // We can't represent the addition or subtraction of two symbols. if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) return false; + // At this point, we have at most one additive symbol and one subtractive + // symbol -- find them. const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; - if (B) { - // If we have a negated symbol, then we must have also have a non-negated - // symbol in order to encode the expression. We can do this check later to - // permit expressions which eventually fold to a representable form -- such - // as (a + (0 - b)) -- if necessary. - if (!A) - return false; - } + + // If we have a negated symbol, then we must have also have a non-negated + // symbol in order to encode the expression. + if (B && !A) + return false; // Absolutize symbol differences between defined symbols when we have a // layout object and the target requests it. |