Skip to content

Commit

Permalink
[norm] Simplify int normalizations by removing endianness configurabi…
Browse files Browse the repository at this point in the history
…lity (#295)
  • Loading branch information
titzer authored Nov 4, 2024
1 parent 8189a76 commit ff7b5f6
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 171 deletions.
27 changes: 9 additions & 18 deletions aeneas/src/ir/IntNormalizer.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// See LICENSE for details of Apache 2.0 license.

// Normalizes integers by scattering/gathering the bits to/from multiple integers.
class IntNormalizer(width: byte, bigEndian: bool) {
class IntNormalizer(width: byte) {
def intMask = (1 << width) - 1;
def cache = TypeUtil.newTypeMap<IntNorm>();
def word = Int.getType(false, width);
Expand All @@ -18,13 +18,11 @@ class IntNormalizer(width: byte, bigEndian: bool) {
var negative = tt.signed && v < 0;
for (i < words) {
var bits = Int.box(v & intMask);
if (bigEndian) array[index + words - i] = bits;
else array[index + i] = bits;
array[index + i] = bits;
v = v >>> width;
}
if (negative) v = v | -1 << width;
if (bigEndian) array[index] = Int.box(v);
else array[index + words] = Int.box(v);
array[index + words] = Int.box(v);
}
// Normalize a long value into an array of values.
def normLongIntoArray(tt: IntType, v: long, array: Array<Val>, index: int) {
Expand All @@ -34,13 +32,8 @@ class IntNormalizer(width: byte, bigEndian: bool) {
}
if (width == 32) {
var t = Long.split(v), high = Int.box(t.0), low = Int.box(t.1);
if (bigEndian) {
array[index] = high;
array[index + 1] = low;
} else {
array[index] = low;
array[index + 1] = high;
}
array[index] = low;
array[index + 1] = high;
return;
}
// XXX: general case of normalizing a long is ugly and slow!
Expand All @@ -49,13 +42,11 @@ class IntNormalizer(width: byte, bigEndian: bool) {
var negative = tt.signed && v < 0;
for (i < words) {
var bits = box(v & mask);
if (bigEndian) array[index + words - i] = bits;
else array[index + i] = bits;
array[index + i] = bits;
v = v >>> width;
}
if (negative) v = v | (-1L << width);
if (bigEndian) array[index] = box(v);
else array[index + words] = box(v);
array[index + words] = box(v);
}
def normType(t: Type) -> IntNorm {
if (!IntType.?(t)) return null;
Expand All @@ -70,9 +61,9 @@ class IntNormalizer(width: byte, bigEndian: bool) {
var sub = Array<Type>.new(words + 1);
for (i < sub.length) sub[i] = word;
var bigEnd = Int.getType(oldType.signed, oldType.width - words * width);
sub[if(bigEndian, 0, sub.length - 1)] = bigEnd;
sub[if(false, 0, sub.length - 1)] = bigEnd;
var newType = Tuple.newType(Lists.fromArray(sub));
nt = IntNorm.new(oldType, newType, sub, bigEndian);
nt = IntNorm.new(oldType, newType, sub);
cache[oldType] = nt;
}
return nt;
Expand Down
4 changes: 2 additions & 2 deletions aeneas/src/ir/Reachability.v3
Original file line number Diff line number Diff line change
Expand Up @@ -864,8 +864,8 @@ class VariantComparatorGen(context: SsaContext, root: IrClass, receiver: IrClass
}
// Globally shareable normalizers.
component IntNormalizers {
def I32LE = IntNormalizer.new(32, false);
def I64LE = IntNormalizer.new(64, false);
def I32LE = IntNormalizer.new(32);
def I64LE = IntNormalizer.new(64);
}
// Reports code that is neither used during initialization nor reachable from main().
class DeadCodeAnalyzer(ra: ReachabilityAnalyzer) {
Expand Down
41 changes: 13 additions & 28 deletions aeneas/src/ir/TypeNorm.v3
Original file line number Diff line number Diff line change
Expand Up @@ -32,53 +32,38 @@ class TypeNorm(oldType: Type, newType: Type, sub: Array<Type>) {
}
// Integer types might be split into multiple words for target machines < 64 bit.
class IntNorm extends TypeNorm {
def bigEndian: bool;
new(oldType: Type, newType: Type, sub: Array<Type>, bigEndian)
new(oldType: Type, newType: Type, sub: Array<Type>)
super(oldType, newType, sub) { }
def bigEndIndex() -> int {
return if(bigEndian, 0, size - 1);
return if(false, 0, size - 1);
}
def littleEndIndex() -> int {
return if(bigEndian, size - 1, 0);
return if(false, size - 1, 0);
}
// Select {n} items from {input} corresponding to the low-order words.
def getLowestN<T>(inputs: Array<T>, n: int) -> Array<T> {
if (bigEndian) return Arrays.range(inputs, inputs.length - n, inputs.length); // [big,vN,...,v0]
else return Arrays.range(inputs, 0, n); // [v0,...,vN,big]
return Arrays.range(inputs, 0, n); // [v0,...,vN,big]
}
// Create a new array of {n} items, copying the low order words from {inputs} and
// extending the upper words with {extend}.
def growToN<T>(inputs: Array<T>, n: int, extend: T) -> Array<T> {
var result = Array<T>.new(n);
if (bigEndian) {
var d = n - 1;
for (i = inputs.length - 1; i >= 0; i--) result[d--] = inputs[i];
while (d >= 0) result[d--] = extend;
} else {
var d = 0;
for (i = 0; i < size; i++) result[d++] = inputs[i];
while (d < result.length) result[d++] = extend;
}
var d = 0;
for (i = 0; i < size; i++) result[d++] = inputs[i];
while (d < result.length) result[d++] = extend;
return result;
}
// Simulate a shift left by {n} words, filling in the vacant entries with {extend}.
def shiftLeft<T>(inputs: Array<T>, n: int, extend: T) {
shift(true, inputs, n, extend);
var i = size - 1;
while (i >= n) { inputs[i] = inputs[i - n]; i--; }
while (i >= 0) { inputs[i] = extend; i--; }
}
// Simulate a shift right by {n} words, filling in the vacant entries with {extend}.
def shiftRight<T>(inputs: Array<T>, n: int, extend: T) {
shift(false, inputs, n, extend);
}
def shift<T>(left: bool, inputs: Array<T>, n: int, extend: T) {
if (left == bigEndian) {
var i = 0;
while (i < size - n) { inputs[i] = inputs[i + n]; i++; }
while (i < size) { inputs[i] = extend; i++; }
} else {
var i = size - 1;
while (i >= n) { inputs[i] = inputs[i - n]; i--; }
while (i >= 0) { inputs[i] = extend; i--; }
}
var i = 0;
while (i < size - n) { inputs[i] = inputs[i + n]; i++; }
while (i < size) { inputs[i] = extend; i++; }
}
}
// Arrays of tuples may be represented as a tuple of arrays or mixed elements, or a
Expand Down
4 changes: 2 additions & 2 deletions aeneas/src/mach/MachLowering.v3
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ class MachLowering(mach: MachProgram, compiler: Compiler, config: MachLoweringCo
var op = if(i == tn.littleEndIndex(), infixL, infixH)(tt);
var i_cmp = apply(i_old.source, op, [i_a, i_b]);
var i_eq = apply(i_old.source, tt.opEq(), [i_a, i_b]);
var next = i + if(mach.intNorm.bigEndian, 1, -1);
var next = i + if(false, 1, -1);
var i_sub = genIntCmpRec(i_old, tn, ai_new, next, infixH, infixL);
var i_and = apply(i_old.source, V3Op.opBoolAnd, [i_eq, i_sub]);
return apply(i_old.source, V3Op.opBoolOr, [i_cmp, i_and]);
Expand Down Expand Up @@ -2121,7 +2121,7 @@ def decomposeByteArrayAccess(mach: MachProgram, config: MachLoweringConfig, fiel
var intType = Int.getType(false, width);
var tn = mach.intNorm.makeType(intType), sub = tn.sub;
var accesses = Array<Access>.new(sub.length);
if (mach.intNorm.bigEndian != (fieldOrder == ByteOrder.BIG_ENDIAN)) {
if (fieldOrder == ByteOrder.BIG_ENDIAN) {
for (i = sub.length - 1; i >= 0; i--) {
var compound = compoundAccess(mach, sub[i], fieldOrder, offset);
accesses[i] = compound;
Expand Down
2 changes: 1 addition & 1 deletion aeneas/src/main/Version.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

// Updated by VCS scripts. DO NOT EDIT.
component Version {
def version: string = "III-7.1766";
def version: string = "III-7.1767";
var buildData: string;
}
Loading

0 comments on commit ff7b5f6

Please sign in to comment.