aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCExpr.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2023-06-22 12:24:19 -0700
committerFangrui Song <i@maskray.me>2023-06-22 12:24:19 -0700
commitfb294c0612a12f2a39be90df0c3a22f66d4ab9f7 (patch)
treea286b1e9d63b09e2c710d44e6a5c0d70b032f716 /llvm/lib/MC/MCExpr.cpp
parentdc9f69e483dd70b15ff260a98dc2a3dcadc93016 (diff)
downloadllvm-fb294c0612a12f2a39be90df0c3a22f66d4ab9f7.zip
llvm-fb294c0612a12f2a39be90df0c3a22f66d4ab9f7.tar.gz
llvm-fb294c0612a12f2a39be90df0c3a22f66d4ab9f7.tar.bz2
[MC] Fold A-B when A's fragment precedes B's fragment
When the MCAssembler is non-null and the MCAsmLayout is null, we can fold A-B when * A and B are in the same fragment, or * A's fragment suceeds B's fragment, and they are not separated by non-data fragments (D69411) This patch allows folding when A's fragment precedes B's fragment so that `9997b - . == 0` below can be evaluated as true: ``` nop .arch_extension sec 9997:nop // old behavior: error: expected absolute expression .if 9997b - . == 0 .endif ``` Add a case to llvm/test/MC/ARM/directive-if-subtraction.s. Note: for MCAsmStreamer, we cannot evaluate `.if . - 9997b == 0` at parse time due to MCAsmStreamer::getAssemblerPtr returning nullptr (D45164). Some Darwin tests check that this folding does not work. Add `.p2align 2` to block some label difference folding or adjust the tests. Reviewed By: nickdesaulniers Differential Revision: https://reviews.llvm.org/D153096
Diffstat (limited to 'llvm/lib/MC/MCExpr.cpp')
-rw-r--r--llvm/lib/MC/MCExpr.cpp25
1 files changed, 18 insertions, 7 deletions
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index c2ecc00..b161904 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -660,6 +660,18 @@ static void AttemptToFoldSymbolOffsetDifference(
// Try to find a constant displacement from FA to FB, add the displacement
// between the offset in FA of SA and the offset in FB of SB.
int64_t Displacement = SA.getOffset() - SB.getOffset();
+ bool Reverse = false;
+ if (FA == FB) {
+ Reverse = SA.getOffset() < SB.getOffset();
+ } else if (!isa<MCDummyFragment>(FA)) {
+ Reverse = std::find_if(std::next(FA->getIterator()), SecA.end(),
+ [&](auto &I) { return &I == FB; }) != SecA.end();
+ }
+ if (Reverse) {
+ std::swap(FA, FB);
+ Displacement *= -1;
+ }
+
bool Found = false;
for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) {
auto DF = dyn_cast<MCDataFragment>(FI);
@@ -678,13 +690,12 @@ static void AttemptToFoldSymbolOffsetDifference(
return;
}
}
- // If FA is found or if FA is a dummy fragment not in the fragment list,
- // (which means SA is a pending label (see flushPendingLabels)), we can
- // resolve the difference.
- if (Found || isa<MCDummyFragment>(FA)) {
- Addend += Displacement;
- FinalizeFolding();
- }
+ // If the previous loop does not find FA, FA must be a dummy fragment not in
+ // the fragment list (which means SA is a pending label (see
+ // flushPendingLabels)). In either case, we can resolve the difference.
+ assert(Found || isa<MCDummyFragment>(FA));
+ Addend += Reverse ? -Displacement : Displacement;
+ FinalizeFolding();
}
}