Skip to content

Commit 292974b

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

9 files changed

+169
-160
lines changed

src/compiler.ts

Lines changed: 97 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,66 @@ 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+
switch (_BinaryenExpressionGetId(expr)) {
7117+
case ExpressionId.Binary: {
7118+
switch (_BinaryenBinaryGetOp(expr)) {
7119+
case BinaryOp.EqI32:
7120+
case BinaryOp.EqI64:
7121+
case BinaryOp.EqF32:
7122+
case BinaryOp.EqF64:
7123+
case BinaryOp.LtI32:
7124+
case BinaryOp.LtU32:
7125+
case BinaryOp.LtI64:
7126+
case BinaryOp.LtU64:
7127+
case BinaryOp.LtF32:
7128+
case BinaryOp.LtF64:
7129+
case BinaryOp.LeI32:
7130+
case BinaryOp.LeU32:
7131+
case BinaryOp.LeI64:
7132+
case BinaryOp.LeU64:
7133+
case BinaryOp.LeF32:
7134+
case BinaryOp.LeF64:
7135+
case BinaryOp.GtI32:
7136+
case BinaryOp.GtU32:
7137+
case BinaryOp.GtI64:
7138+
case BinaryOp.GtU64:
7139+
case BinaryOp.GtF32:
7140+
case BinaryOp.GtF64:
7141+
case BinaryOp.GeI32:
7142+
case BinaryOp.GeU32:
7143+
case BinaryOp.GeI64:
7144+
case BinaryOp.GeU64:
7145+
case BinaryOp.GeF32:
7146+
case BinaryOp.GeF64: return false;
7147+
case BinaryOp.AndI32: return mightOverflow(_BinaryenBinaryGetRight(expr), type);
7148+
}
7149+
break;
7150+
}
7151+
case ExpressionId.Unary: {
7152+
switch (_BinaryenUnaryGetOp(expr)) {
7153+
case UnaryOp.EqzI32:
7154+
case UnaryOp.EqzI64: return false;
7155+
case UnaryOp.ClzI32:
7156+
case UnaryOp.CtzI32: return type.size < 7; // max value is 32 (100000b)
7157+
}
7158+
break;
7159+
}
7160+
case ExpressionId.Const: {
7161+
if (_BinaryenExpressionGetType(expr) == NativeType.I32) {
7162+
let value = _BinaryenConstGetValueI32(expr);
7163+
switch (type.kind) {
7164+
case TypeKind.I8: return value < i8.MIN_VALUE || value > i8.MAX_VALUE;
7165+
case TypeKind.I16: return value < i16.MIN_VALUE || value > i16.MAX_VALUE;
7166+
case TypeKind.U8: return value < 0 || value > u8.MAX_VALUE;
7167+
case TypeKind.U16: return value < 0 || value > u16.MAX_VALUE;
7168+
}
7169+
}
7170+
return false;
7171+
}
7172+
}
7173+
return true;
7174+
}

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: 6 additions & 9 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
)

tests/compiler/std/array-access.untouched.wat

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,13 @@
163163
(if
164164
(if (result i32)
165165
(get_local $2)
166-
(i32.and
167-
(i32.eq
168-
(i32.load8_u
169-
(get_local $0)
170-
)
171-
(i32.load8_u
172-
(get_local $1)
173-
)
166+
(i32.eq
167+
(i32.load8_u
168+
(get_local $0)
169+
)
170+
(i32.load8_u
171+
(get_local $1)
174172
)
175-
(i32.const 1)
176173
)
177174
(get_local $2)
178175
)

tests/compiler/std/array.untouched.wat

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5665,19 +5665,13 @@
56655665
)
56665666
(func $std/array/assertSortedDefault<i32>~anonymous|42 (; 86 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
56675667
(i32.sub
5668-
(i32.and
5669-
(i32.gt_s
5670-
(get_local $0)
5671-
(get_local $1)
5672-
)
5673-
(i32.const 1)
5668+
(i32.gt_s
5669+
(get_local $0)
5670+
(get_local $1)
56745671
)
5675-
(i32.and
5676-
(i32.lt_s
5677-
(get_local $0)
5678-
(get_local $1)
5679-
)
5680-
(i32.const 1)
5672+
(i32.lt_s
5673+
(get_local $0)
5674+
(get_local $1)
56815675
)
56825676
)
56835677
)
@@ -9287,16 +9281,13 @@
92879281
(if
92889282
(if (result i32)
92899283
(get_local $2)
9290-
(i32.and
9291-
(i32.eq
9292-
(i32.load8_u
9293-
(get_local $0)
9294-
)
9295-
(i32.load8_u
9296-
(get_local $1)
9297-
)
9284+
(i32.eq
9285+
(i32.load8_u
9286+
(get_local $0)
9287+
)
9288+
(i32.load8_u
9289+
(get_local $1)
92989290
)
9299-
(i32.const 1)
93009291
)
93019292
(get_local $2)
93029293
)

tests/compiler/std/libm.untouched.wat

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,18 +2457,15 @@
24572457
(i32.const 2)
24582458
)
24592459
)
2460-
(i32.and
2461-
(i32.lt_u
2462-
(i32.add
2463-
(get_local $6)
2464-
(i32.shl
2465-
(i32.const 64)
2466-
(i32.const 20)
2467-
)
2460+
(i32.lt_u
2461+
(i32.add
2462+
(get_local $6)
2463+
(i32.shl
2464+
(i32.const 64)
2465+
(i32.const 20)
24682466
)
2469-
(get_local $4)
24702467
)
2471-
(i32.const 1)
2468+
(get_local $4)
24722469
)
24732470
(get_local $2)
24742471
)

0 commit comments

Comments
 (0)