Unreachability

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Oct 17 20:55:55 UTC 2024


Paul,
the fix you propose looks (very) good.

Luckily, the alive analyzer is one of the simplest visitors we have in 
Flow - and we also have to run it as part of lambda type-checking. So it 
should be safely reusable, like you did.

Maurizio

On 17/10/2024 00:16, Paul Sandoz wrote:
> Here’s a possible fix:
>
>          CoreOp.FuncOp scanMethod() {
>              scan(body);
>              appendReturnOrUnreachable(body);
>              CoreOp.FuncOp func = CoreOp.func(name.toString(), stack.body);
>              func.setLocation(generateLocation(currentNode, true));
>              return func;
>          }
>
>          private <O extends Op & Op.Terminating> void appendReturnOrUnreachable(JCTree body) {
>              // Append only if an existing terminating operation is not present
>              if (lastOp == null || !(lastOp instanceof Op.Terminating)) {
>                  if (isReachable(body)) {
>                      append(CoreOp._return());
>                  } else {
>                      append(CoreOp.unreachable());
>                  }
>              }
>          }
>
>          boolean isReachable(JCTree node) {
>              return flow.aliveAfter(typeEnvs.get(currentClassSym), node, make);
>          }
>
> Paul.
>
>> On Oct 16, 2024, at 1:18 PM, Paul Sandoz <paul.sandoz at oracle.com> wrote:
>>
>> Hi,
>>
>> Gary encountered an issue when transforming say:
>>
>>     @CodeReflection
>>     public static float f(float input) {
>>         if (input >= 0f) {
>>             return 1f;
>>         } else {
>>             return 0f;
>>         }
>>         // Unreachable
>>     }
>>
>> Compiler produced model:
>>
>> func @"f" @loc="10:5:..." (%0 : float)float -> {
>>     %1 : Var<float> = var %0 @"input" @loc="10:5";
>>     java.if @loc="13:9"
>>         ()boolean -> {
>>             %2 : float = var.load %1 @loc="13:13";
>>             %3 : float = constant @"0.0" @loc="13:22";
>>             %4 : boolean = ge %2 %3 @loc="13:13";
>>             yield %4 @loc="13:9";
>>         }
>>         ()void -> {
>>             %5 : float = constant @"1.0" @loc="14:20";
>>             return %5 @loc="14:13";
>>         }
>>         ()void -> {
>>             %6 : float = constant @"0.0" @loc="16:20";
>>             return %6 @loc="16:13";
>>         };
>>     return @loc="10:5";
>> };
>>
>> Lowered model:
>>
>> func @"f" @loc="10:5:..." (%0 : float)float -> {
>>     %1 : Var<float> = var %0 @"input" @loc="10:5";
>>     %2 : float = var.load %1 @loc="13:13";
>>     %3 : float = constant @"0.0" @loc="13:22";
>>     %4 : boolean = ge %2 %3 @loc="13:13";
>>     cbranch %4 ^block_1 ^block_2;
>>
>>   ^block_1:
>>     %5 : float = constant @"1.0" @loc="14:20";
>>     return %5 @loc="14:13";
>>
>>   ^block_2:
>>     %6 : float = constant @"0.0" @loc="16:20";
>>     return %6 @loc="16:13";
>>
>>   ^block_3:
>>     return @loc="10:5";
>> };
>>
>>
>> The compiler produced model is incorrect placing a return operation when it should be an unreachable operation.
>>
>> There are some reminders in ReflectMethods:
>>
>>         CoreOp.FuncOp scanMethod() {
>>             scan(body);
>>             // @@@ Check if unreachable
>>             appendTerminating(CoreOp::_return);
>>             CoreOp.FuncOp func = CoreOp.func(name.toString(), stack.body);
>>             func.setLocation(generateLocation(currentNode, true));
>>             return func;
>>         }
>>
>> We need to determine if the last statement yields control or not. (It’s easy to see if we lower, as ^block_3 is never referenced.)
>>
>> In this case we can know because there is no return value in scope, but generally we cannot rely upon that.
>>
>> The compiler already checks this, I believe in Flow.AliveAnalyzer. However, it does not add additional information to the attributed tree - it does not need to.
>>
>> Can we reuse the method Flow.aliveAfter? Although I don’t know how to get access to an instance of Env<AttrContext>. Do we get it from TypeEnvs?
>>
>> Paul.


More information about the babylon-dev mailing list