Skip to content

Commit 33bcd10

Browse files
committed
Do not extend if expression kind does not overflow
1 parent 40bbbcd commit 33bcd10

10 files changed

+202
-212
lines changed

src/compiler.ts

Lines changed: 102 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6856,56 +6856,56 @@ export class Compiler extends DiagnosticEmitter {
68566856
/** Makes sure that a 32-bit integer value is wrapped to a valid value of the specified type. */
68576857
makeSmallIntegerWrap(expr: ExpressionRef, type: Type): ExpressionRef {
68586858
var module = this.module;
6859-
var isI32 = (
6860-
_BinaryenExpressionGetId(expr) == ExpressionId.Const &&
6861-
_BinaryenExpressionGetType(expr) == NativeType.I32
6862-
);
6863-
var i32Value = isI32 ? _BinaryenConstGetValueI32(expr) : 0;
68646859
switch (type.kind) {
68656860
case TypeKind.I8: { // TODO: Use 'i32.extend8_s' once sign-extension-ops lands
6866-
if (isI32 && i32Value >= i8.MIN_VALUE && i32Value <= i8.MAX_VALUE) break;
6867-
expr = module.createBinary(BinaryOp.ShrI32,
6868-
module.createBinary(BinaryOp.ShlI32,
6869-
expr,
6861+
if (mightOverflow(expr, type)) {
6862+
expr = module.createBinary(BinaryOp.ShrI32,
6863+
module.createBinary(BinaryOp.ShlI32,
6864+
expr,
6865+
module.createI32(24)
6866+
),
68706867
module.createI32(24)
6871-
),
6872-
module.createI32(24)
6873-
);
6868+
);
6869+
}
68746870
break;
68756871
}
68766872
case TypeKind.I16: { // TODO: Use 'i32.extend16_s' once sign-extension-ops lands
6877-
if (isI32 && i32Value >= i16.MIN_VALUE && i32Value <= i16.MAX_VALUE) break;
6878-
expr = module.createBinary(BinaryOp.ShrI32,
6879-
module.createBinary(BinaryOp.ShlI32,
6880-
expr,
6873+
if (mightOverflow(expr, type)) {
6874+
expr = module.createBinary(BinaryOp.ShrI32,
6875+
module.createBinary(BinaryOp.ShlI32,
6876+
expr,
6877+
module.createI32(16)
6878+
),
68816879
module.createI32(16)
6882-
),
6883-
module.createI32(16)
6884-
);
6880+
);
6881+
}
68856882
break;
68866883
}
68876884
case TypeKind.U8: {
6888-
if (isI32 && i32Value >= u8.MIN_VALUE && i32Value <= u8.MAX_VALUE) break;
6889-
expr = module.createBinary(BinaryOp.AndI32,
6890-
expr,
6891-
module.createI32(0xff)
6892-
);
6885+
if (mightOverflow(expr, type)) {
6886+
expr = module.createBinary(BinaryOp.AndI32,
6887+
expr,
6888+
module.createI32(0xff)
6889+
);
6890+
}
68936891
break;
68946892
}
68956893
case TypeKind.U16: {
6896-
if (isI32 && i32Value >= u16.MIN_VALUE && i32Value <= u16.MAX_VALUE) break;
6897-
expr = module.createBinary(BinaryOp.AndI32,
6898-
expr,
6899-
module.createI32(0xffff)
6900-
);
6894+
if (mightOverflow(expr, type)) {
6895+
expr = module.createBinary(BinaryOp.AndI32,
6896+
expr,
6897+
module.createI32(0xffff)
6898+
);
6899+
}
69016900
break;
69026901
}
69036902
case TypeKind.BOOL: {
6904-
if (isI32 && !(i32Value & ~1)) break;
6905-
expr = module.createBinary(BinaryOp.AndI32,
6906-
expr,
6907-
module.createI32(0x1)
6908-
);
6903+
if (mightOverflow(expr, type)) {
6904+
expr = module.createBinary(BinaryOp.AndI32,
6905+
expr,
6906+
module.createI32(0x1)
6907+
);
6908+
}
69096909
break;
69106910
}
69116911
}
@@ -7109,3 +7109,71 @@ function mangleExportName(element: Element, explicitSimpleName: string | null =
71097109
}
71107110
}
71117111
}
7112+
7113+
/** Tests if an expression might overflow, in a general sense. */
7114+
function mightOverflow(expr: ExpressionRef, type: Type): bool {
7115+
assert(type.is(TypeFlags.INTEGER));
7116+
assert(_BinaryenExpressionGetType(expr) == NativeType.I32);
7117+
switch (_BinaryenExpressionGetId(expr)) {
7118+
case ExpressionId.Binary: {
7119+
switch (_BinaryenBinaryGetOp(expr)) {
7120+
case BinaryOp.EqI32:
7121+
case BinaryOp.EqI64:
7122+
case BinaryOp.EqF32:
7123+
case BinaryOp.EqF64:
7124+
case BinaryOp.LtI32:
7125+
case BinaryOp.LtU32:
7126+
case BinaryOp.LtI64:
7127+
case BinaryOp.LtU64:
7128+
case BinaryOp.LtF32:
7129+
case BinaryOp.LtF64:
7130+
case BinaryOp.LeI32:
7131+
case BinaryOp.LeU32:
7132+
case BinaryOp.LeI64:
7133+
case BinaryOp.LeU64:
7134+
case BinaryOp.LeF32:
7135+
case BinaryOp.LeF64:
7136+
case BinaryOp.GtI32:
7137+
case BinaryOp.GtU32:
7138+
case BinaryOp.GtI64:
7139+
case BinaryOp.GtU64:
7140+
case BinaryOp.GtF32:
7141+
case BinaryOp.GtF64:
7142+
case BinaryOp.GeI32:
7143+
case BinaryOp.GeU32:
7144+
case BinaryOp.GeI64:
7145+
case BinaryOp.GeU64:
7146+
case BinaryOp.GeF32:
7147+
case BinaryOp.GeF64: return false;
7148+
case BinaryOp.AndI32: return mightOverflow(_BinaryenBinaryGetRight(expr), type);
7149+
}
7150+
break;
7151+
}
7152+
case ExpressionId.Unary: {
7153+
switch (_BinaryenUnaryGetOp(expr)) {
7154+
case UnaryOp.EqzI32:
7155+
case UnaryOp.EqzI64: return false;
7156+
case UnaryOp.ClzI32:
7157+
case UnaryOp.CtzI32: return type.size < 7; // max value is 32 (100000b)
7158+
}
7159+
break;
7160+
}
7161+
case ExpressionId.Const: {
7162+
if (_BinaryenExpressionGetType(expr) == NativeType.I32) {
7163+
let value = _BinaryenConstGetValueI32(expr);
7164+
switch (type.kind) {
7165+
case TypeKind.I8: return value < i8.MIN_VALUE || value > i8.MAX_VALUE;
7166+
case TypeKind.I16: return value < i16.MIN_VALUE || value > i16.MAX_VALUE;
7167+
case TypeKind.U8: return value < 0 || value > u8.MAX_VALUE;
7168+
case TypeKind.U16: return value < 0 || value > u16.MAX_VALUE;
7169+
}
7170+
}
7171+
return false;
7172+
}
7173+
case ExpressionId.Load: {
7174+
return type.byteSize < _BinaryenLoadGetBytes(expr)
7175+
|| type.is(TypeFlags.SIGNED) != _BinaryenLoadIsSigned(expr);
7176+
}
7177+
}
7178+
return true;
7179+
}

tests/compiler/memset.untouched.wat

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,8 @@
395395
(if
396396
(i32.eqz
397397
(i32.eq
398-
(i32.and
399-
(i32.load8_u
400-
(get_global $memset/dest)
401-
)
402-
(i32.const 255)
398+
(i32.load8_u
399+
(get_global $memset/dest)
403400
)
404401
(i32.const 1)
405402
)
@@ -417,14 +414,11 @@
417414
(if
418415
(i32.eqz
419416
(i32.eq
420-
(i32.and
421-
(i32.load8_u
422-
(i32.add
423-
(get_global $memset/dest)
424-
(i32.const 15)
425-
)
417+
(i32.load8_u
418+
(i32.add
419+
(get_global $memset/dest)
420+
(i32.const 15)
426421
)
427-
(i32.const 255)
428422
)
429423
(i32.const 1)
430424
)
@@ -452,11 +446,8 @@
452446
(if
453447
(i32.eqz
454448
(i32.eq
455-
(i32.and
456-
(i32.load8_u
457-
(get_global $memset/dest)
458-
)
459-
(i32.const 255)
449+
(i32.load8_u
450+
(get_global $memset/dest)
460451
)
461452
(i32.const 1)
462453
)
@@ -474,14 +465,11 @@
474465
(if
475466
(i32.eqz
476467
(i32.eq
477-
(i32.and
478-
(i32.load8_u
479-
(i32.add
480-
(get_global $memset/dest)
481-
(i32.const 1)
482-
)
468+
(i32.load8_u
469+
(i32.add
470+
(get_global $memset/dest)
471+
(i32.const 1)
483472
)
484-
(i32.const 255)
485473
)
486474
(i32.const 2)
487475
)
@@ -499,14 +487,11 @@
499487
(if
500488
(i32.eqz
501489
(i32.eq
502-
(i32.and
503-
(i32.load8_u
504-
(i32.add
505-
(get_global $memset/dest)
506-
(i32.const 14)
507-
)
490+
(i32.load8_u
491+
(i32.add
492+
(get_global $memset/dest)
493+
(i32.const 14)
508494
)
509-
(i32.const 255)
510495
)
511496
(i32.const 2)
512497
)
@@ -524,14 +509,11 @@
524509
(if
525510
(i32.eqz
526511
(i32.eq
527-
(i32.and
528-
(i32.load8_u
529-
(i32.add
530-
(get_global $memset/dest)
531-
(i32.const 15)
532-
)
512+
(i32.load8_u
513+
(i32.add
514+
(get_global $memset/dest)
515+
(i32.const 15)
533516
)
534-
(i32.const 255)
535517
)
536518
(i32.const 1)
537519
)

tests/compiler/showcase.untouched.wat

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6049,10 +6049,7 @@
60496049
(i32.const -1)
60506050
)
60516051
(set_global $unary/i
6052-
(i32.and
6053-
(i32.eqz
6054-
(i32.const 1)
6055-
)
6052+
(i32.eqz
60566053
(i32.const 1)
60576054
)
60586055
)
@@ -6072,11 +6069,8 @@
60726069
)
60736070
)
60746071
(set_global $unary/i
6075-
(i32.and
6076-
(i32.eqz
6077-
(get_global $unary/i)
6078-
)
6079-
(i32.const 1)
6072+
(i32.eqz
6073+
(get_global $unary/i)
60806074
)
60816075
)
60826076
(set_global $unary/i
@@ -6315,12 +6309,9 @@
63156309
(f32.const -1.25)
63166310
)
63176311
(set_global $unary/i
6318-
(i32.and
6319-
(f64.eq
6320-
(f64.const 1.25)
6321-
(f64.const 0)
6322-
)
6323-
(i32.const 1)
6312+
(f64.eq
6313+
(f64.const 1.25)
6314+
(f64.const 0)
63246315
)
63256316
)
63266317
(set_global $unary/f
@@ -6332,12 +6323,9 @@
63326323
)
63336324
)
63346325
(set_global $unary/i
6335-
(i32.and
6336-
(f32.eq
6337-
(get_global $unary/f)
6338-
(f32.const 0)
6339-
)
6340-
(i32.const 1)
6326+
(f32.eq
6327+
(get_global $unary/f)
6328+
(f32.const 0)
63416329
)
63426330
)
63436331
(set_global $unary/f

tests/compiler/std/allocator_arena.untouched.wat

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2622,16 +2622,13 @@
26222622
(if
26232623
(if (result i32)
26242624
(get_local $2)
2625-
(i32.and
2626-
(i32.eq
2627-
(i32.load8_u
2628-
(get_local $0)
2629-
)
2630-
(i32.load8_u
2631-
(get_local $1)
2632-
)
2625+
(i32.eq
2626+
(i32.load8_u
2627+
(get_local $0)
2628+
)
2629+
(i32.load8_u
2630+
(get_local $1)
26332631
)
2634-
(i32.const 1)
26352632
)
26362633
(get_local $2)
26372634
)
@@ -2745,14 +2742,11 @@
27452742
(if
27462743
(i32.eqz
27472744
(i32.eq
2748-
(i32.and
2749-
(i32.load8_u
2750-
(i32.add
2751-
(get_global $std/allocator_arena/ptr1)
2752-
(get_global $std/allocator_arena/i)
2753-
)
2745+
(i32.load8_u
2746+
(i32.add
2747+
(get_global $std/allocator_arena/ptr1)
2748+
(get_global $std/allocator_arena/i)
27542749
)
2755-
(i32.const 255)
27562750
)
27572751
(i32.const 18)
27582752
)
@@ -2797,14 +2791,11 @@
27972791
(if
27982792
(i32.eqz
27992793
(i32.eq
2800-
(i32.and
2801-
(i32.load8_u
2802-
(i32.add
2803-
(get_global $std/allocator_arena/ptr2)
2804-
(get_global $std/allocator_arena/i)
2805-
)
2794+
(i32.load8_u
2795+
(i32.add
2796+
(get_global $std/allocator_arena/ptr2)
2797+
(get_global $std/allocator_arena/i)
28062798
)
2807-
(i32.const 255)
28082799
)
28092800
(i32.const 18)
28102801
)

0 commit comments

Comments
 (0)