Skip to content

Commit 2bdc098

Browse files
authored
Emit condition check at the end of loop (#12959)
* Emit condition check at the end of loop * Update baselines files * Move debug point, update more baselines * Fix more IL tests * Fix GenWhileLoop when the stack is not empty, add 2 more tests * Fix baselines after merge
1 parent 6aa2635 commit 2bdc098

File tree

66 files changed

+12481
-12637
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+12481
-12637
lines changed

src/fsharp/IlxGen.fs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4107,18 +4107,45 @@ and GenIntegerForLoop cenv cgbuf eenv (spFor, spTo, v, e1, dir, e2, loopBody, m)
41074107

41084108
and GenWhileLoop cenv cgbuf eenv (spWhile, condExpr, bodyExpr, m) sequel =
41094109
let eenv = SetIsInLoop true eenv
4110-
let finish = CG.GenerateDelayMark cgbuf "while_finish"
41114110

4112-
match spWhile with
4113-
| DebugPointAtWhile.Yes spStart -> CG.EmitDebugPoint cgbuf spStart
4114-
| DebugPointAtWhile.No -> ()
4111+
// jmp test; body; test; if testPassed then jmp body else finish
4112+
//
4113+
// This is a pattern recognized by the JIT and it results in the most efficient assembly.
4114+
if cgbuf.GetCurrentStack().IsEmpty then
4115+
let startTest = CG.GenerateDelayMark cgbuf "startTest"
4116+
CG.EmitInstr cgbuf (pop 0) Push0 (I_br startTest.CodeLabel)
41154117

4116-
let startTest = CG.GenerateMark cgbuf "startTest"
4118+
let startBody = CG.GenerateMark cgbuf "startBody"
4119+
GenExpr cenv cgbuf eenv bodyExpr discard
41174120

4118-
GenExpr cenv cgbuf eenv condExpr (CmpThenBrOrContinue (pop 1, [ I_brcmp(BI_brfalse, finish.CodeLabel) ]))
4121+
match spWhile with
4122+
| DebugPointAtWhile.Yes spStart -> CG.EmitDebugPoint cgbuf spStart
4123+
| DebugPointAtWhile.No -> ()
41194124

4120-
GenExpr cenv cgbuf eenv bodyExpr (DiscardThen (Br startTest))
4121-
CG.SetMarkToHere cgbuf finish
4125+
CG.SetMarkToHere cgbuf startTest
4126+
GenExpr cenv cgbuf eenv condExpr (CmpThenBrOrContinue (pop 1, [ I_brcmp (BI_brtrue, startBody.CodeLabel) ]))
4127+
4128+
// In the rare cases when there is something already on the stack, e.g.
4129+
//
4130+
// let f() =
4131+
// callSomething firstArgument ((while .... do ...); secondArgument)
4132+
//
4133+
// we emit
4134+
//
4135+
// test; if not testPassed jmp finish; body; jmp test; finish
4136+
else
4137+
let finish = CG.GenerateDelayMark cgbuf "while_finish"
4138+
4139+
match spWhile with
4140+
| DebugPointAtWhile.Yes spStart -> CG.EmitDebugPoint cgbuf spStart
4141+
| DebugPointAtWhile.No -> ()
4142+
4143+
let startTest = CG.GenerateMark cgbuf "startTest"
4144+
4145+
GenExpr cenv cgbuf eenv condExpr (CmpThenBrOrContinue (pop 1, [ I_brcmp (BI_brfalse, finish.CodeLabel) ]))
4146+
4147+
GenExpr cenv cgbuf eenv bodyExpr (DiscardThen (Br startTest))
4148+
CG.SetMarkToHere cgbuf finish
41224149

41234150
GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel
41244151

tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForEachOnList01.fs.il.net472.debug.bsl

Lines changed: 147 additions & 154 deletions
Large diffs are not rendered by default.

tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForEachOnList01.fs.il.net472.release.bsl

Lines changed: 156 additions & 163 deletions
Large diffs are not rendered by default.

tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForEachOnList01.fs.il.netcore.debug.bsl

Lines changed: 147 additions & 154 deletions
Large diffs are not rendered by default.

tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForEachOnList01.fs.il.netcore.release.bsl

Lines changed: 156 additions & 163 deletions
Large diffs are not rendered by default.

tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/NonTrivialBranchingBindingInEnd03.fs.il.bsl

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@
2828
}
2929
.mresource public FSharpSignatureData.NonTrivialBranchingBindingInEnd03
3030
{
31-
// Offset: 0x00000000 Length: 0x00000279
31+
// Offset: 0x00000000 Length: 0x00000283
3232
// WARNING: managed resource file FSharpSignatureData.NonTrivialBranchingBindingInEnd03 created
3333
}
3434
.mresource public FSharpOptimizationData.NonTrivialBranchingBindingInEnd03
3535
{
36-
// Offset: 0x00000280 Length: 0x000000A6
36+
// Offset: 0x00000288 Length: 0x000000A6
3737
// WARNING: managed resource file FSharpOptimizationData.NonTrivialBranchingBindingInEnd03 created
3838
}
3939
.module NonTrivialBranchingBindingInEnd03.exe
40-
// MVID: {624FA9CC-169A-A7F7-A745-0383CCA94F62}
40+
// MVID: {62507741-169A-A7F7-A745-038341775062}
4141
.imagebase 0x00400000
4242
.file alignment 0x00000200
4343
.stackreserve 0x00100000
4444
.subsystem 0x0003 // WINDOWS_CUI
4545
.corflags 0x00000001 // ILONLY
46-
// Image base: 0x00E70000
46+
// Image base: 0x02FB0000
4747

4848

4949
// =============== CLASS MEMBERS DECLARATION ===================
@@ -184,7 +184,7 @@
184184
.method public static void main@() cil managed
185185
{
186186
.entrypoint
187-
// Code size 222 (0xde)
187+
// Code size 221 (0xdd)
188188
.maxstack 7
189189
.locals init (int32 V_0)
190190
IL_0000: ldc.i4.8
@@ -228,47 +228,46 @@
228228
IL_0062: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
229229
IL_0067: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
230230
IL_006c: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> '<StartupCode$NonTrivialBranchingBindingInEnd03>'.$NonTrivialBranchingBindingInEnd03::next@9
231-
IL_0071: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
232-
IL_0076: brfalse.s IL_00c1
231+
IL_0071: br.s IL_00b9
233232

234-
IL_0078: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
235-
IL_007d: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_HeadOrDefault()
236-
IL_0082: stloc.0
237-
IL_0083: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
238-
IL_0088: ldloc.0
239-
IL_0089: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
240-
IL_008e: ldloc.0
241-
IL_008f: ldelem [mscorlib]System.Int32
242-
IL_0094: call int32[] NonTrivialBranchingBindingInEnd03::get_w()
243-
IL_0099: ldloc.0
244-
IL_009a: ldelem [mscorlib]System.Int32
245-
IL_009f: add
246-
IL_00a0: stelem [mscorlib]System.Int32
247-
IL_00a5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
248-
IL_00aa: call void NonTrivialBranchingBindingInEnd03::set_current@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
249-
IL_00af: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
250-
IL_00b4: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
251-
IL_00b9: call void NonTrivialBranchingBindingInEnd03::set_next@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
252-
IL_00be: nop
253-
IL_00bf: br.s IL_0071
233+
IL_0073: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
234+
IL_0078: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_HeadOrDefault()
235+
IL_007d: stloc.0
236+
IL_007e: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
237+
IL_0083: ldloc.0
238+
IL_0084: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
239+
IL_0089: ldloc.0
240+
IL_008a: ldelem [mscorlib]System.Int32
241+
IL_008f: call int32[] NonTrivialBranchingBindingInEnd03::get_w()
242+
IL_0094: ldloc.0
243+
IL_0095: ldelem [mscorlib]System.Int32
244+
IL_009a: add
245+
IL_009b: stelem [mscorlib]System.Int32
246+
IL_00a0: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
247+
IL_00a5: call void NonTrivialBranchingBindingInEnd03::set_current@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
248+
IL_00aa: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
249+
IL_00af: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
250+
IL_00b4: call void NonTrivialBranchingBindingInEnd03::set_next@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
251+
IL_00b9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
252+
IL_00be: brtrue.s IL_0073
254253

254+
IL_00c0: nop
255255
IL_00c1: nop
256-
IL_00c2: nop
257-
IL_00c3: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
258-
IL_00c8: ldc.i4.0
259-
IL_00c9: ldelem [mscorlib]System.Int32
260-
IL_00ce: ldc.i4.3
261-
IL_00cf: bne.un.s IL_00d5
256+
IL_00c2: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
257+
IL_00c7: ldc.i4.0
258+
IL_00c8: ldelem [mscorlib]System.Int32
259+
IL_00cd: ldc.i4.3
260+
IL_00ce: bne.un.s IL_00d4
262261

263-
IL_00d1: ldc.i4.0
264-
IL_00d2: nop
265-
IL_00d3: br.s IL_00d7
262+
IL_00d0: ldc.i4.0
263+
IL_00d1: nop
264+
IL_00d2: br.s IL_00d6
266265

267-
IL_00d5: ldc.i4.1
268-
IL_00d6: nop
269-
IL_00d7: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Exit<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(int32)
270-
IL_00dc: pop
271-
IL_00dd: ret
266+
IL_00d4: ldc.i4.1
267+
IL_00d5: nop
268+
IL_00d6: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Exit<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(int32)
269+
IL_00db: pop
270+
IL_00dc: ret
272271
} // end of method $NonTrivialBranchingBindingInEnd03::main@
273272

274273
} // end of class '<StartupCode$NonTrivialBranchingBindingInEnd03>'.$NonTrivialBranchingBindingInEnd03

tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/NonTrivialBranchingBindingInEnd03.fs.opt.il.bsl

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@
2828
}
2929
.mresource public FSharpSignatureData.NonTrivialBranchingBindingInEnd03
3030
{
31-
// Offset: 0x00000000 Length: 0x00000276
31+
// Offset: 0x00000000 Length: 0x00000280
3232
// WARNING: managed resource file FSharpSignatureData.NonTrivialBranchingBindingInEnd03 created
3333
}
3434
.mresource public FSharpOptimizationData.NonTrivialBranchingBindingInEnd03
3535
{
36-
// Offset: 0x00000280 Length: 0x000000A6
36+
// Offset: 0x00000288 Length: 0x000000A6
3737
// WARNING: managed resource file FSharpOptimizationData.NonTrivialBranchingBindingInEnd03 created
3838
}
3939
.module NonTrivialBranchingBindingInEnd03.exe
40-
// MVID: {624FA9CC-169A-A7F7-A745-0383CCA94F62}
40+
// MVID: {62507741-169A-A7F7-A745-038341775062}
4141
.imagebase 0x00400000
4242
.file alignment 0x00000200
4343
.stackreserve 0x00100000
4444
.subsystem 0x0003 // WINDOWS_CUI
4545
.corflags 0x00000001 // ILONLY
46-
// Image base: 0x03050000
46+
// Image base: 0x03490000
4747

4848

4949
// =============== CLASS MEMBERS DECLARATION ===================
@@ -184,7 +184,7 @@
184184
.method public static void main@() cil managed
185185
{
186186
.entrypoint
187-
// Code size 222 (0xde)
187+
// Code size 221 (0xdd)
188188
.maxstack 7
189189
.locals init (int32 V_0)
190190
IL_0000: ldc.i4.8
@@ -228,47 +228,46 @@
228228
IL_0062: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
229229
IL_0067: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
230230
IL_006c: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> '<StartupCode$NonTrivialBranchingBindingInEnd03>'.$NonTrivialBranchingBindingInEnd03::next@9
231-
IL_0071: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
232-
IL_0076: brfalse.s IL_00c1
231+
IL_0071: br.s IL_00b9
233232

234-
IL_0078: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
235-
IL_007d: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_HeadOrDefault()
236-
IL_0082: stloc.0
237-
IL_0083: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
238-
IL_0088: ldloc.0
239-
IL_0089: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
240-
IL_008e: ldloc.0
241-
IL_008f: ldelem [mscorlib]System.Int32
242-
IL_0094: call int32[] NonTrivialBranchingBindingInEnd03::get_w()
243-
IL_0099: ldloc.0
244-
IL_009a: ldelem [mscorlib]System.Int32
245-
IL_009f: add
246-
IL_00a0: stelem [mscorlib]System.Int32
247-
IL_00a5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
248-
IL_00aa: call void NonTrivialBranchingBindingInEnd03::set_current@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
249-
IL_00af: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
250-
IL_00b4: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
251-
IL_00b9: call void NonTrivialBranchingBindingInEnd03::set_next@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
252-
IL_00be: nop
253-
IL_00bf: br.s IL_0071
233+
IL_0073: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
234+
IL_0078: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_HeadOrDefault()
235+
IL_007d: stloc.0
236+
IL_007e: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
237+
IL_0083: ldloc.0
238+
IL_0084: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
239+
IL_0089: ldloc.0
240+
IL_008a: ldelem [mscorlib]System.Int32
241+
IL_008f: call int32[] NonTrivialBranchingBindingInEnd03::get_w()
242+
IL_0094: ldloc.0
243+
IL_0095: ldelem [mscorlib]System.Int32
244+
IL_009a: add
245+
IL_009b: stelem [mscorlib]System.Int32
246+
IL_00a0: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
247+
IL_00a5: call void NonTrivialBranchingBindingInEnd03::set_current@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
248+
IL_00aa: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_current@9()
249+
IL_00af: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
250+
IL_00b4: call void NonTrivialBranchingBindingInEnd03::set_next@9(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>)
251+
IL_00b9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> NonTrivialBranchingBindingInEnd03::get_next@9()
252+
IL_00be: brtrue.s IL_0073
254253

254+
IL_00c0: nop
255255
IL_00c1: nop
256-
IL_00c2: nop
257-
IL_00c3: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
258-
IL_00c8: ldc.i4.0
259-
IL_00c9: ldelem [mscorlib]System.Int32
260-
IL_00ce: ldc.i4.3
261-
IL_00cf: bne.un.s IL_00d5
256+
IL_00c2: call int32[] NonTrivialBranchingBindingInEnd03::get_r()
257+
IL_00c7: ldc.i4.0
258+
IL_00c8: ldelem [mscorlib]System.Int32
259+
IL_00cd: ldc.i4.3
260+
IL_00ce: bne.un.s IL_00d4
262261

263-
IL_00d1: ldc.i4.0
264-
IL_00d2: nop
265-
IL_00d3: br.s IL_00d7
262+
IL_00d0: ldc.i4.0
263+
IL_00d1: nop
264+
IL_00d2: br.s IL_00d6
266265

267-
IL_00d5: ldc.i4.1
268-
IL_00d6: nop
269-
IL_00d7: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Exit<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(int32)
270-
IL_00dc: pop
271-
IL_00dd: ret
266+
IL_00d4: ldc.i4.1
267+
IL_00d5: nop
268+
IL_00d6: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::Exit<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(int32)
269+
IL_00db: pop
270+
IL_00dc: ret
272271
} // end of method $NonTrivialBranchingBindingInEnd03::main@
273272

274273
} // end of class '<StartupCode$NonTrivialBranchingBindingInEnd03>'.$NonTrivialBranchingBindingInEnd03

0 commit comments

Comments
 (0)