Variable Assignment Fix #287

Merged
sb10q merged 1 commits from 285-fix-var-assign into master 2022-05-14 16:00:37 +08:00
Collaborator

This is an attempt to fix #285 by fixing the gen_store_target function: when generating assignment target of an existing variable, the static value stored previously in ctx.var_assignment should be cleared in case that the assigned value is not an static value anymore. Some cases of assignment to a StaticValue is possible and should pass the type check of kernel invariant, just like the case of #285.

Doing this should not harm KernelInvariant optimization, since the static value in var_assignment will still get updated if the assignment value is static, which will be used when accessing the value here

for this code

from min_artiq import *
from numpy import int32

WE = 4096
CONFIG_ADDR = 3072


@extern
def print_int32(x: int32):
    ...

@nac3
class Test:
    @kernel
    def set_config(self):
        self.write(CONFIG_ADDR)

    @kernel
    def write(self, addr: int32):
        print_int32(addr)
        addr |= WE
        print_int32(addr)
        addr = addr & 0xff
        print_int32(addr)

@nac3
class Demo:
    core: KernelInvariant[Core]
    test: KernelInvariant[Test]

    def __init__(self):
       self.core = Core()
       self.test = Test()


    @kernel
    def run(self):
        self.test.set_config()
    
if __name__ == "__main__":
    Demo().run()
IR before this patch
; ModuleID = 'main'
source_filename = "main"

%__main__.Test = type {}
%min_artiq.Core = type { double }
%__main__.Demo = type { %min_artiq.Core*, %__main__.Test* }

@"140400399959472" = global %__main__.Test zeroinitializer
@"140400399959808" = global %min_artiq.Core { double 1.000000e-09 }
@"140400399959616" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"140400399959808", %__main__.Test* @"140400399959472" }
@tagptr0 = private global [2 x i8] c":n"
@"2400020124162657182" = private global { i8*, i64 } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tagptr0, i32 0, i32 0), i64 2 }

declare i32 @__nac3_personality(...)

declare void @print_int32(i32) local_unnamed_addr

define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality !dbg !8 {
init:
  %argptr1.i = alloca [0 x i8*], align 8
  tail call void @print_int32(i32 3072), !dbg !13
  tail call void @print_int32(i32 3072), !dbg !20
  tail call void @print_int32(i32 3072), !dbg !21
  %0 = bitcast [0 x i8*]* %argptr1.i to i8*, !dbg !22
  call void @llvm.lifetime.start.p0i8(i64 0, i8* nonnull %0), !dbg !22
  %rpc.stack.i = tail call i8* @llvm.stacksave(), !dbg !22
  %argptr1.sub.i = getelementptr inbounds [0 x i8*], [0 x i8*]* %argptr1.i, i64 0, i64 0, !dbg !22
  call void @rpc_send(i32 0, { i8*, i64 }* nonnull @"2400020124162657182", i8** nonnull %argptr1.sub.i), !dbg !22
  call void @llvm.stackrestore(i8* %rpc.stack.i), !dbg !22
  %rpc_recv.i = call i32 @rpc_recv(i8* null), !dbg !22
  call void @llvm.lifetime.end.p0i8(i64 0, i8* nonnull %0), !dbg !22
  ret void, !dbg !22
}

; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare i8* @llvm.stacksave() #0

declare void @rpc_send(i32, { i8*, i64 }*, i8**) local_unnamed_addr

; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare void @llvm.stackrestore(i8*) #0

declare i32 @rpc_recv(i8*) local_unnamed_addr

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1

attributes #0 = { mustprogress nofree nosync nounwind willreturn }
attributes #1 = { argmemonly nofree nosync nounwind willreturn }
IR after this patch
; ModuleID = 'main'
source_filename = "main"

%min_artiq.Core = type { double }
%__main__.Demo = type { %min_artiq.Core*, %__main__.Test* }
%__main__.Test = type {}

@"140564064941824" = global %min_artiq.Core { double 1.000000e-09 }
@"140564064941632" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"140564064941824", %__main__.Test* @"140564064941488" }
@"140564064941488" = global %__main__.Test zeroinitializer
@tagptr0 = private global [2 x i8] c":n"
@"2400020124162657182" = private global { i8*, i64 } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tagptr0, i32 0, i32 0), i64 2 }

declare i32 @__nac3_personality(...)

declare void @print_int32(i32) local_unnamed_addr

define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality !dbg !8 {
init:
  %argptr1.i = alloca [0 x i8*], align 8
  tail call void @print_int32(i32 3072), !dbg !13
  tail call void @print_int32(i32 7168), !dbg !20
  tail call void @print_int32(i32 0), !dbg !21
  %0 = bitcast [0 x i8*]* %argptr1.i to i8*, !dbg !22
  call void @llvm.lifetime.start.p0i8(i64 0, i8* nonnull %0), !dbg !22
  %rpc.stack.i = tail call i8* @llvm.stacksave(), !dbg !22
  %argptr1.sub.i = getelementptr inbounds [0 x i8*], [0 x i8*]* %argptr1.i, i64 0, i64 0, !dbg !22
  call void @rpc_send(i32 0, { i8*, i64 }* nonnull @"2400020124162657182", i8** nonnull %argptr1.sub.i), !dbg !22
  call void @llvm.stackrestore(i8* %rpc.stack.i), !dbg !22
  %rpc_recv.i = call i32 @rpc_recv(i8* null), !dbg !22
  call void @llvm.lifetime.end.p0i8(i64 0, i8* nonnull %0), !dbg !22
  ret void, !dbg !22
}

; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare i8* @llvm.stacksave() #0

declare void @rpc_send(i32, { i8*, i64 }*, i8**) local_unnamed_addr

; Function Attrs: mustprogress nofree nosync nounwind willreturn
declare void @llvm.stackrestore(i8*) #0

declare i32 @rpc_recv(i8*) local_unnamed_addr

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1

attributes #0 = { mustprogress nofree nosync nounwind willreturn }
attributes #1 = { argmemonly nofree nosync nounwind willreturn }
This is an attempt to fix #285 by fixing the `gen_store_target` function: when generating assignment target of an existing variable, the static value stored previously in `ctx.var_assignment` should be cleared in case that the assigned value is not an static value anymore. Some cases of assignment to a `StaticValue` is possible and should pass the type check of kernel invariant, just like the case of #285. Doing this should not harm `KernelInvariant` optimization, since the static value in `var_assignment` [will still get updated](https://git.m-labs.hk/M-Labs/nac3/src/branch/master/nac3core/src/codegen/stmt.rs#L195-L197) if the assignment value is static, which will be used when accessing the value [here](https://git.m-labs.hk/M-Labs/nac3/src/branch/master/nac3core/src/codegen/expr.rs#L1059) for this code ```python from min_artiq import * from numpy import int32 WE = 4096 CONFIG_ADDR = 3072 @extern def print_int32(x: int32): ... @nac3 class Test: @kernel def set_config(self): self.write(CONFIG_ADDR) @kernel def write(self, addr: int32): print_int32(addr) addr |= WE print_int32(addr) addr = addr & 0xff print_int32(addr) @nac3 class Demo: core: KernelInvariant[Core] test: KernelInvariant[Test] def __init__(self): self.core = Core() self.test = Test() @kernel def run(self): self.test.set_config() if __name__ == "__main__": Demo().run() ``` <details> <summary> IR before this patch </summary> ```llvm ; ModuleID = 'main' source_filename = "main" %__main__.Test = type {} %min_artiq.Core = type { double } %__main__.Demo = type { %min_artiq.Core*, %__main__.Test* } @"140400399959472" = global %__main__.Test zeroinitializer @"140400399959808" = global %min_artiq.Core { double 1.000000e-09 } @"140400399959616" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"140400399959808", %__main__.Test* @"140400399959472" } @tagptr0 = private global [2 x i8] c":n" @"2400020124162657182" = private global { i8*, i64 } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tagptr0, i32 0, i32 0), i64 2 } declare i32 @__nac3_personality(...) declare void @print_int32(i32) local_unnamed_addr define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality !dbg !8 { init: %argptr1.i = alloca [0 x i8*], align 8 tail call void @print_int32(i32 3072), !dbg !13 tail call void @print_int32(i32 3072), !dbg !20 tail call void @print_int32(i32 3072), !dbg !21 %0 = bitcast [0 x i8*]* %argptr1.i to i8*, !dbg !22 call void @llvm.lifetime.start.p0i8(i64 0, i8* nonnull %0), !dbg !22 %rpc.stack.i = tail call i8* @llvm.stacksave(), !dbg !22 %argptr1.sub.i = getelementptr inbounds [0 x i8*], [0 x i8*]* %argptr1.i, i64 0, i64 0, !dbg !22 call void @rpc_send(i32 0, { i8*, i64 }* nonnull @"2400020124162657182", i8** nonnull %argptr1.sub.i), !dbg !22 call void @llvm.stackrestore(i8* %rpc.stack.i), !dbg !22 %rpc_recv.i = call i32 @rpc_recv(i8* null), !dbg !22 call void @llvm.lifetime.end.p0i8(i64 0, i8* nonnull %0), !dbg !22 ret void, !dbg !22 } ; Function Attrs: mustprogress nofree nosync nounwind willreturn declare i8* @llvm.stacksave() #0 declare void @rpc_send(i32, { i8*, i64 }*, i8**) local_unnamed_addr ; Function Attrs: mustprogress nofree nosync nounwind willreturn declare void @llvm.stackrestore(i8*) #0 declare i32 @rpc_recv(i8*) local_unnamed_addr ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 attributes #0 = { mustprogress nofree nosync nounwind willreturn } attributes #1 = { argmemonly nofree nosync nounwind willreturn } ``` </details> <details> <summary> IR after this patch </summary> ```llvm ; ModuleID = 'main' source_filename = "main" %min_artiq.Core = type { double } %__main__.Demo = type { %min_artiq.Core*, %__main__.Test* } %__main__.Test = type {} @"140564064941824" = global %min_artiq.Core { double 1.000000e-09 } @"140564064941632" = local_unnamed_addr global %__main__.Demo { %min_artiq.Core* @"140564064941824", %__main__.Test* @"140564064941488" } @"140564064941488" = global %__main__.Test zeroinitializer @tagptr0 = private global [2 x i8] c":n" @"2400020124162657182" = private global { i8*, i64 } { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tagptr0, i32 0, i32 0), i64 2 } declare i32 @__nac3_personality(...) declare void @print_int32(i32) local_unnamed_addr define void @__modinit__() local_unnamed_addr personality i32 (...)* @__nac3_personality !dbg !8 { init: %argptr1.i = alloca [0 x i8*], align 8 tail call void @print_int32(i32 3072), !dbg !13 tail call void @print_int32(i32 7168), !dbg !20 tail call void @print_int32(i32 0), !dbg !21 %0 = bitcast [0 x i8*]* %argptr1.i to i8*, !dbg !22 call void @llvm.lifetime.start.p0i8(i64 0, i8* nonnull %0), !dbg !22 %rpc.stack.i = tail call i8* @llvm.stacksave(), !dbg !22 %argptr1.sub.i = getelementptr inbounds [0 x i8*], [0 x i8*]* %argptr1.i, i64 0, i64 0, !dbg !22 call void @rpc_send(i32 0, { i8*, i64 }* nonnull @"2400020124162657182", i8** nonnull %argptr1.sub.i), !dbg !22 call void @llvm.stackrestore(i8* %rpc.stack.i), !dbg !22 %rpc_recv.i = call i32 @rpc_recv(i8* null), !dbg !22 call void @llvm.lifetime.end.p0i8(i64 0, i8* nonnull %0), !dbg !22 ret void, !dbg !22 } ; Function Attrs: mustprogress nofree nosync nounwind willreturn declare i8* @llvm.stacksave() #0 declare void @rpc_send(i32, { i8*, i64 }*, i8**) local_unnamed_addr ; Function Attrs: mustprogress nofree nosync nounwind willreturn declare void @llvm.stackrestore(i8*) #0 declare i32 @rpc_recv(i8*) local_unnamed_addr ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 ; Function Attrs: argmemonly nofree nosync nounwind willreturn declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 attributes #0 = { mustprogress nofree nosync nounwind willreturn } attributes #1 = { argmemonly nofree nosync nounwind willreturn } ``` </details>
ychenfo added 1 commit 2022-05-14 02:49:50 +08:00
sb10q merged commit 096f4b03c0 into master 2022-05-14 16:00:37 +08:00
sb10q deleted branch 285-fix-var-assign 2022-05-14 16:00:39 +08:00
Sign in to join this conversation.
No reviewers
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: M-Labs/nac3#287
No description provided.