dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.29k stars 1.59k forks source link

Simplify branch conditions based on ranges & simplify control flow afterwards if condition turns out to be constant #56096

Open mkustermann opened 5 months ago

mkustermann commented 5 months ago

This

import 'dart:typed_data';

import 'package:benchmark_harness/benchmark_harness.dart';

void main() {
  Foo().report();
  if (int.parse('1') == 1) print(sink);
}

final XX = Uint8List.fromList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

final class Foo extends BenchmarkBase {
  Foo() : super('Uint8List.fromList');

  @override
  @pragma('vm:never-inline')
  void run() {
    sink = Uint8List.fromList(XX);
  }
}

var sink;

currently generates this code

*** BEGIN CFG
After GenerateCode
  0: B0[graph]:0 {
      v0 <- Constant(#null) T{Null?}
      v17 <- Constant(#0) [0, 0] T{_Smi}
      v176 <- Constant(#1048576) [1048576, 1048576] T{_Smi}
      v203 <- UnboxedConstant(#0) [0, 0] int64
}
  2: B1[function entry]:2 {
      v2 <- Parameter(0 @rdi) T{Foo}
}
  4:     CheckStackOverflow:8(stack=0, loop=0)
  6:     v7 <- LoadStaticField:4(XX, CallsInitializer) T{_Uint8List}
  7:     ParallelMove rcx <- rax
  8:     ParallelMove fp[-2] <- rcx
  8:     v22 <- LoadField(v7 T{_Uint8List} . TypedDataBase.length {final}) [0, 4611686018427387903] T{_Smi}
  9:     ParallelMove rax <- rdx, fp[-1] <- rdx
 10:     v28 <- AllocateTypedData:10(v22 T{_Smi}) T{_Uint8List}
 12:     ParallelMove rcx <- fp[-1], fp[-4] <- rax
 12:     v201 <- UnboxInt64([non-speculative], v22 T{_Smi}) [0, 4611686018427387903] int64
 13:     ParallelMove fp[-3] <- rcx
 14:     Branch if RelationalOp(>, v203 T{_Smi}, v201 T{_Smi}) T{bool} goto (28, 25)
 16: B28[target]:48
 18:     ParallelMove  goto:50 B26
 20: B25[target]:40
 22:     Branch if RelationalOp(>, v201 T{_Smi}, v201 T{_Smi}) T{bool} goto (29, 30)
 24: B29[target]:52
 26:     ParallelMove  goto:54 B26
 28: B26[join]:42 pred(B28, B29)
 29:     ParallelMove rdi <- C, rsi <- fp[-1], rdx <- rcx
 30:     StaticCall:58( checkValidRange<0> v203 T{_Smi}, v22 T{_Smi}, v201 T{_Smi}) int64
 32:     ParallelMove  goto:64 B35
 34: B30[target]:60
 36:     ParallelMove  goto:66 B35
 38: B35[join]:62 pred(B26, B30) ParallelMove rdx <- fp[-3]
 40:     Branch if RelationalOp(<, v201 T{_Smi}, v201 T{_Smi}) T{bool} goto (36, 37)
 84: B36[target]:126
 86:     v82 <- StaticCall:128( tooFew<0> ) T{StateError}
 88:     Throw:130(v82)
 42: B37[target]:132
 44:     Branch if EqualityCompare(v201 T{_Smi} == v203 T{_Smi}) T{bool} goto (38, 39)
 46: B38[target]:142
 48:     ParallelMove r12 <- fp[-4] goto:146 B43
 50: B39[target]:148 ParallelMove rcx <- fp[-1]
 52:     Branch if RelationalOp:12(<, v22 T{_Smi}, v176 T{_Smi}) T{bool} goto (59, 60)
 54: B59[target]:18 ParallelMove rax <- fp[-2], r12 <- fp[-4]
 56:     MemoryCopy(v7 T{_Uint8List}, v28 T{_Uint8List}, v17 T{_Smi}, v17 T{_Smi}, v22 T{_Smi}, dest_cid=_Int8List (111), src_cid=_Int8List (111), can_overlap)
 58:     ParallelMove  goto:12 B58
 60: B60[target]:20 ParallelMove rax <- fp[-2], r12 <- fp[-4]
 62:     v165 <- LoadField(v28 T{_Uint8List} . PointerBase.data, MayLoadInnerPointer) untagged
 64:     v168 <- LoadField(v7 T{_Uint8List} . PointerBase.data, MayLoadInnerPointer) untagged
 66:     v170 <- LoadThread() untagged
 68:     v171 <- LoadUntagged(v170, 1536) untagged
 69:     ParallelMove rdi <- rdi, rsi <- rsi, rdx <- rdx, rax <- rcx
 70:     LeafRuntimeCall(target_address=v171, v165 T{Object}, v168 T{Object}, v201 T{int}) untagged
 72:     ParallelMove  goto:12 B58
 74: B58[join]:10 pred(B59, B60)
 76:     ParallelMove  goto:154 B43
 78: B43[join]:33 pred(B38, B58)
 79:     ParallelMove rax <- r12
 80:     StoreStaticField(sink, v28 T{_Uint8List})
 81:     ParallelMove rax <- C
 82:     DartReturn:18(v0)
*** END CFG

This can be optimized, e.g. the following branch can be eliminated:

*** BEGIN CFG
After GenerateCode
 B0[graph]:0 {
      v203 <- UnboxedConstant(#0) [0, 0] int64
  }
    v201 <- UnboxInt64([non-speculative], v22 T{_Smi}) [0, 4611686018427387903] int64
    Branch if RelationalOp(>, v203 T{_Smi}, v201 T{_Smi}) T{bool} goto (28, 25)

/cc @mraleph

a-siva commented 4 weeks ago

//cc @aam downgraded priority as referenced issue has a P3 priority