diff options
author | Fangrui Song <i@maskray.me> | 2023-06-22 12:24:19 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2023-06-22 12:24:19 -0700 |
commit | fb294c0612a12f2a39be90df0c3a22f66d4ab9f7 (patch) | |
tree | a286b1e9d63b09e2c710d44e6a5c0d70b032f716 /llvm/lib/MC/MCExpr.cpp | |
parent | dc9f69e483dd70b15ff260a98dc2a3dcadc93016 (diff) | |
download | llvm-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.cpp | 25 |
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(); } } |