Skip to content

Commit 8068546

Browse files
Martien de Jongmartien-de-jong
authored andcommitted
[AIE] widen RelocationPatch to 256 bits.
1 parent 0f18d34 commit 8068546

1 file changed

Lines changed: 51 additions & 24 deletions

File tree

lld/ELF/Arch/AIE.cpp

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
7-
// (c) Copyright 2023-2024 Advanced Micro Devices, Inc. or its affiliates
7+
// (c) Copyright 2023-2025 Advanced Micro Devices, Inc. or its affiliates
88
//
99
//===----------------------------------------------------------------------===//
1010

@@ -136,64 +136,91 @@ static void writeNBytes(int N, uint8_t *Loc, uint64_t Value) {
136136
/// aligns the field value to the right position, selects bits from the
137137
/// image and the patch field using a selection mask and writes the result
138138
/// back to the section data.
139-
class Patch {
140-
// Workspace
141-
uint64_t val[2];
139+
class RelocationPatch {
140+
// Workspace (256-bit = 4x64-bit lanes)
141+
uint64_t val[4];
142142

143143
public:
144-
Patch() {
144+
RelocationPatch() {
145145
val[0] = 0;
146146
val[1] = 0;
147+
val[2] = 0;
148+
val[3] = 0;
147149
}
148-
Patch(uint64_t vl, uint64_t vh = 0) {
150+
RelocationPatch(uint64_t vl, uint64_t vh = 0) {
149151
val[0] = vl;
150152
val[1] = vh;
153+
val[2] = 0;
154+
val[3] = 0;
151155
}
152156

153157
/// Construct a value from the \p n bytes in memory pointed by \p loc
154-
Patch(int n, uint8_t *loc) {
155-
assert(n <= 16);
158+
/// Widened to support up to 32 bytes (256 bits).
159+
RelocationPatch(int n, uint8_t *loc) {
160+
assert(n <= 32);
156161
int i = 0;
157162
while (n > 8) {
158163
val[i++] = readNBytes(8, loc);
159164
n -= 8;
160165
loc += 8;
161166
}
162167
val[i] = readNBytes(n, loc);
168+
// Zero any remaining lanes
169+
while (++i < 4)
170+
val[i] = 0;
163171
}
164172

165-
/// Shift \p *this left by \p shift bits
166-
Patch operator<<(int shift) {
167-
Patch r;
168-
assert(shift < 64);
169-
if (shift >= 64) {
170-
r.val[1] = val[0] << (shift - 64);
173+
/// Shift \p *this left by \p shift bits (0 <= shift < 256)
174+
RelocationPatch operator<<(int shift) const {
175+
RelocationPatch r = *this;
176+
assert(shift < 256);
177+
assert(shift >= 0);
178+
if (shift == 0) {
179+
// Avoid UB: val[0] >> (64 - shift) would right-shift by 64 when shift==0.
180+
return r;
181+
}
182+
183+
// First shift by words
184+
while (shift >= 64) {
185+
for (int i = 3; i > 0; i--) {
186+
r.val[i] = r.val[i - 1];
187+
}
171188
r.val[0] = 0;
172-
} else {
173-
r.val[0] = val[0] << shift;
174-
r.val[1] = (val[0] >> (64 - shift)) | (val[1] << shift);
189+
shift -= 64;
175190
}
191+
192+
// Then shift remaining bits across words
193+
if (shift != 0) {
194+
const int rshift = 64 - shift;
195+
for (int i = 3; i > 0; i--) {
196+
r.val[i] = (r.val[i] << shift) | (r.val[i - 1] >> rshift);
197+
}
198+
r.val[0] = r.val[0] << shift;
199+
}
200+
176201
return r;
177202
}
178203

179204
/// Patch \size bits of \p field at position \p shift in the workspace
180-
void patch(Patch field, uint32_t size, uint32_t shift) {
205+
void patch(RelocationPatch field, uint32_t size, uint32_t shift) {
181206
assert(size <= 64);
182207
// Create a mask of the field size
183-
Patch mask(~(~uint64_t(0) << size));
208+
RelocationPatch mask(~(size == 64 ? uint64_t(0) : ~uint64_t(0) << size));
184209

185210
// Shift both into position
186211
field = field << shift;
187212
mask = mask << shift;
188213

189-
// Do the insertion
214+
// Do the insertion across all lanes
190215
val[0] = (val[0] & ~mask.val[0]) | (field.val[0] & mask.val[0]);
191216
val[1] = (val[1] & ~mask.val[1]) | (field.val[1] & mask.val[1]);
217+
val[2] = (val[2] & ~mask.val[2]) | (field.val[2] & mask.val[2]);
218+
val[3] = (val[3] & ~mask.val[3]) | (field.val[3] & mask.val[3]);
192219
}
193220

194221
/// Write the \p n bytes patch back to memory at location \p loc
195222
void write(int n, uint8_t *loc) {
196-
assert(n <= 16);
223+
assert(n <= 32);
197224
int i = 0;
198225
while (n > 8) {
199226
writeNBytes(8, loc, val[i++]);
@@ -230,14 +257,14 @@ static void patchNBytes(uint32_t N, uint8_t *Loc, uint64_t V, uint32_t Hi,
230257
assert(Pos + FieldSize <= BitSize);
231258

232259
// Read bytes to be patched in wide representation
233-
Patch Image(N, Loc);
260+
RelocationPatch Image(N, Loc);
234261

235262
// Pos is the msb, the shift count needs the lsb
236-
uint32_t Shift = BitSize - Pos - FieldSize;
263+
const uint32_t Shift = BitSize - Pos - FieldSize;
237264

238265
// Align field with bit 0, and put it in a wide representation.
239266
// Excess high bits will be masked off when patching
240-
Patch Field(V >> Lo);
267+
RelocationPatch Field(V >> Lo);
241268

242269
// Patch it
243270
Image.patch(Field, FieldSize, Shift);

0 commit comments

Comments
 (0)