Skip to content

Commit 88b10f3

Browse files
authored
[MC][AArch64] Segregate constant pool caches by size. (#86832)
If you write a 32- and a 64-bit LDR instruction that both refer to the same constant or symbol using the = syntax: ``` ldr w0, =something ldr x1, =something ``` then the first call to `ConstantPool::addEntry` will insert the constant into its cache of existing entries, and the second one will find the cache entry and reuse it. This results in a 64-bit load from a 32-bit constant, reading nonsense into the other half of the target register. In this patch I've done the simplest fix: include the size of the constant pool entry as part of the key used to index the cache. So now 32- and 64-bit constant loads will never share a constant pool entry. There's scope for doing this better, in principle: you could imagine merging the two slots with appropriate overlap, so that the 32-bit load loads the LSW of the 64-bit value. But that's much more complicated: you have to take endianness into account, and maybe also adjust the size of an existing entry. This is the simplest fix that restores correctness.
1 parent 2a2fd48 commit 88b10f3

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

llvm/include/llvm/MC/ConstantPools.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,13 @@ struct ConstantPoolEntry {
4343
class ConstantPool {
4444
using EntryVecTy = SmallVector<ConstantPoolEntry, 4>;
4545
EntryVecTy Entries;
46-
std::map<int64_t, const MCSymbolRefExpr *> CachedConstantEntries;
47-
DenseMap<const MCSymbol *, const MCSymbolRefExpr *> CachedSymbolEntries;
46+
47+
// Caches of entries that already exist, indexed by their contents
48+
// and also the size of the constant.
49+
std::map<std::pair<int64_t, unsigned>, const MCSymbolRefExpr *>
50+
CachedConstantEntries;
51+
DenseMap<std::pair<const MCSymbol *, unsigned>, const MCSymbolRefExpr *>
52+
CachedSymbolEntries;
4853

4954
public:
5055
// Initialize a new empty constant pool

llvm/lib/MC/ConstantPools.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
4343

4444
// Check if there is existing entry for the same constant. If so, reuse it.
4545
if (C) {
46-
auto CItr = CachedConstantEntries.find(C->getValue());
46+
auto CItr = CachedConstantEntries.find(std::make_pair(C->getValue(), Size));
4747
if (CItr != CachedConstantEntries.end())
4848
return CItr->second;
4949
}
5050

5151
// Check if there is existing entry for the same symbol. If so, reuse it.
5252
if (S) {
53-
auto SItr = CachedSymbolEntries.find(&(S->getSymbol()));
53+
auto SItr =
54+
CachedSymbolEntries.find(std::make_pair(&(S->getSymbol()), Size));
5455
if (SItr != CachedSymbolEntries.end())
5556
return SItr->second;
5657
}
@@ -60,9 +61,9 @@ const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
6061
Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
6162
const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
6263
if (C)
63-
CachedConstantEntries[C->getValue()] = SymRef;
64+
CachedConstantEntries[std::make_pair(C->getValue(), Size)] = SymRef;
6465
if (S)
65-
CachedSymbolEntries[&(S->getSymbol())] = SymRef;
66+
CachedSymbolEntries[std::make_pair(&(S->getSymbol()), Size)] = SymRef;
6667
return SymRef;
6768
}
6869

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: llvm-mc -triple aarch64-none-linux-gnu %s | FileCheck %s
2+
3+
ldr w0, =symbol
4+
ldr x1, =symbol
5+
6+
ldr w2, =1234567890
7+
ldr x3, =1234567890
8+
9+
// CHECK: ldr w0, .Ltmp0
10+
// CHECK: ldr x1, .Ltmp1
11+
// CHECK: ldr w2, .Ltmp2
12+
// CHECK: ldr x3, .Ltmp3
13+
14+
// CHECK: .p2align 2, 0x0
15+
// CHECK-NEXT:.Ltmp0:
16+
// CHECK-NEXT: .word symbol
17+
// CHECK: .p2align 3, 0x0
18+
// CHECK-NEXT:.Ltmp1:
19+
// CHECK-NEXT: .xword symbol
20+
// CHECK: .p2align 2, 0x0
21+
// CHECK-NEXT:.Ltmp2:
22+
// CHECK-NEXT: .word 1234567890
23+
// CHECK: .p2align 3, 0x0
24+
// CHECK-NEXT:.Ltmp3:
25+
// CHECK-NEXT: .xword 1234567890

0 commit comments

Comments
 (0)