@@ -4222,10 +4222,74 @@ class SsaTypeConversionInserter extends HBaseVisitor<void>
4222
4222
List <HBasicBlock >? trueTargets,
4223
4223
List <HBasicBlock >? falseTargets,
4224
4224
) {
4225
+ if (trueTargets == null && falseTargets == null ) return ;
4226
+
4225
4227
for (HInstruction user in instruction.usedBy) {
4226
4228
if (user is HIf ) {
4227
4229
trueTargets? .add (user.thenBlock);
4228
4230
falseTargets? .add (user.elseBlock);
4231
+
4232
+ final joinBlock = user.joinBlock;
4233
+ if (joinBlock != null ) {
4234
+ final joinPredecessors = joinBlock.predecessors;
4235
+ if (joinPredecessors.length == 2 ) {
4236
+ if (hasUnreachableExit (joinPredecessors[0 ])) {
4237
+ // The then-branch does not reach the join block, so the join
4238
+ // block is reached only if condition is false.
4239
+ falseTargets? .add (joinBlock);
4240
+ } else if (hasUnreachableExit (joinPredecessors[1 ])) {
4241
+ // The else-branch does not reach the join block, so the join
4242
+ // block is reached only if condition is true.
4243
+ trueTargets? .add (joinBlock);
4244
+ } else {
4245
+ final phi = joinBlock.phis.firstPhi;
4246
+ if (phi != null && phi.next == null ) {
4247
+ assert (phi.inputs.length == 2 );
4248
+
4249
+ // This is a single phi controlled by `user`.
4250
+ //
4251
+ // Collect the targets of the phi. The phi is in effectively a
4252
+ // conditional `user ? left : right`.
4253
+
4254
+ final right = phi.inputs[1 ];
4255
+ if (right.isConstantFalse ()) {
4256
+ // When `c ? x : false` is true, `c` must be true.
4257
+ // So pass `c`'s trueTargets as the phi's trueTargets.
4258
+ collectTargets (phi, trueTargets, null );
4259
+ } else if (right.isConstantTrue ()) {
4260
+ // When `c ? x : true` is false, `c` must be true.
4261
+ // So pass `c`'s trueTargets as the phi's falseTargets.
4262
+ collectTargets (phi, null , trueTargets);
4263
+ }
4264
+
4265
+ final left = phi.inputs[0 ];
4266
+ if (left.isConstantFalse ()) {
4267
+ // When `c ? false : x` is true, `c` must be false.
4268
+ // So pass `c`'s falseTargets as the phi's trueTargets.
4269
+ collectTargets (phi, falseTargets, null );
4270
+ } else if (left.isConstantTrue ()) {
4271
+ // When `c ? true : x` is false, `c` must be false.
4272
+ // So pass `c`'s falseTargets as the phi's falseTargets.
4273
+ collectTargets (phi, null , falseTargets);
4274
+ }
4275
+
4276
+ // Sanity checks:
4277
+ //
4278
+ // For `c ? true : false`, we pass both `c`'s trueTargets and
4279
+ // falseTargets as the same targets of the phi.
4280
+ //
4281
+ // For `c ? false : true`, we pass the targets reversed, like we
4282
+ // for `HNot`.
4283
+ //
4284
+ // For `c ? false : false`, we pass both `c`'s trueTargets and
4285
+ // falseTargets to the unreachable trueTargets of the phi. We
4286
+ // might insert contradictory strengthenings, which might refine
4287
+ // a value to Never, i.e. we potentially 'prove' the code is
4288
+ // unreachable.
4289
+ }
4290
+ }
4291
+ }
4292
+ }
4229
4293
} else if (user is HLoopBranch ) {
4230
4294
trueTargets? .add (user.block! .successors.first);
4231
4295
// Don't insert refinements on else-branch - may be a critical edge
@@ -4238,9 +4302,10 @@ class SsaTypeConversionInserter extends HBaseVisitor<void>
4238
4302
assert (inputs.contains (instruction));
4239
4303
HInstruction other = inputs[(inputs[0 ] == instruction) ? 1 : 0 ];
4240
4304
if (other.isConstantTrue ()) {
4241
- // The condition flows to a HPhi(true, user), which means that a
4242
- // downstream HIf has true-branch control flow that does not depend
4243
- // on the original instruction, so stop collecting [trueTargets].
4305
+ // The condition flows to `HPhi(true, user)` or `HPhi(user, true)`,
4306
+ // which means that a downstream HIf has true-branch control flow
4307
+ // that does not depend on the original instruction, so stop
4308
+ // collecting [trueTargets].
4244
4309
collectTargets (user, null , falseTargets);
4245
4310
} else if (other.isConstantFalse ()) {
4246
4311
// Ditto for false.
0 commit comments