aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-12-17 05:50:33 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-12-17 05:50:33 +0000
commit17304b3489b7b8ea06dd4df237f15a381ae181ce (patch)
tree00d295e407f5cd2d69878a0995c7d9b8dd54422a /lib
parentb87422778c4e7b828e6e846b81fd77509439c622 (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.cpp52
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.