| // RUN: %eopt --print-activity-analysis --split-input-file %s 2>&1 | FileCheck %s |
| |
| // CHECK-LABEL: @callgraph_sparse: |
| // CHECK: "callres": Active |
| func.func private @mysquare(%arg0: f64) -> f64 { |
| %mul = arith.mulf %arg0, %arg0 : f64 |
| return %mul : f64 |
| } |
| |
| func.func @callgraph_sparse(%arg0: f64) -> f64 { |
| %squared = call @mysquare(%arg0) {tag = "callres"} : (f64) -> f64 |
| return %squared : f64 |
| } |
| |
| // ----- |
| |
| func.func private @noop(%arg0: memref<f64>) { |
| return |
| } |
| |
| // CHECK-LABEL: @callgraph_dense: |
| // CHECK: "sin": Active |
| func.func @callgraph_dense(%arg0: f64) -> f64 { |
| %m = memref.alloc() : memref<f64> |
| memref.store %arg0, %m[] : memref<f64> |
| call @noop(%m) : (memref<f64>) -> () |
| %loaded = memref.load %m[] : memref<f64> |
| %sin = math.sin %loaded {tag = "sin"} : f64 |
| return %sin : f64 |
| } |
| |
| // ----- |
| |
| func.func private @identity(%arg0: memref<f64>) -> memref<f64> { |
| %space = memref.alloc() : memref<memref<f64>> |
| memref.store %arg0, %space[] : memref<memref<f64>> |
| %loaded = memref.load %space[] : memref<memref<f64>> |
| memref.dealloc %space : memref<memref<f64>> |
| return %loaded : memref<f64> |
| } |
| |
| // CHECK-LABEL: @aliased_store: |
| // CHECK: "retval": Active |
| func.func @aliased_store(%arg0: f64) -> f64 { |
| %ptr = memref.alloc() : memref<f64> |
| memref.store %arg0, %ptr[] : memref<f64> |
| %new_ptr = call @identity(%ptr) : (memref<f64>) -> memref<f64> |
| %val = memref.load %new_ptr[] {tag = "retval"} : memref<f64> |
| return %val : f64 |
| } |
| |
| // ----- |
| |
| func.func private @write(%arg0: f64, %ptr: memref<f64>) { |
| memref.store %arg0, %ptr[] : memref<f64> |
| return |
| } |
| |
| func.func private @read(%ptr: memref<f64>) -> f64 { |
| %val = memref.load %ptr[] : memref<f64> |
| return %val : f64 |
| } |
| |
| // CHECK-LABEL: @across_func_boundaries |
| // CHECK: "retval": Active |
| func.func @across_func_boundaries(%arg0: f64) -> f64 { |
| %ptr = memref.alloc() : memref<f64> |
| call @write(%arg0, %ptr) : (f64, memref<f64>) -> () |
| %val = call @read(%ptr) {tag = "retval"} : (memref<f64>) -> f64 |
| return %val : f64 |
| } |
| |
| func.func private @no_write(%arg0: f64, %ptr: memref<f64>) { |
| %cst = arith.constant 3.0 : f64 |
| memref.store %cst, %ptr[] : memref<f64> |
| return |
| } |
| // CHECK-LABEL: @across_func_boundaries_const |
| // CHECK: "retval": Constant |
| func.func @across_func_boundaries_const(%arg0: f64) -> f64 { |
| %ptr = memref.alloc() : memref<f64> |
| call @no_write(%arg0, %ptr) : (f64, memref<f64>) -> () |
| %val = call @read(%ptr) {tag = "retval"} : (memref<f64>) -> f64 |
| return %val : f64 |
| } |
| |
| // ----- |
| |
| // Like across_func_boundaries_const, but in the LLVM dialect |
| llvm.func private @identity(%arg0: !llvm.ptr) -> !llvm.ptr attributes {} { |
| %c4 = llvm.mlir.constant (4) : i64 |
| %mem = memref.alloc() : memref<f32> |
| %nonaliasidx = memref.extract_aligned_pointer_as_index %mem : memref<f32> -> index |
| %nonaliasi64 = arith.index_cast %nonaliasidx : index to i64 |
| %nonalias = llvm.inttoptr %nonaliasi64 : i64 to !llvm.ptr |
| %inner = llvm.mlir.constant (4.5 : f32) : f32 |
| llvm.store %inner, %nonalias : f32, !llvm.ptr |
| llvm.return %nonalias : !llvm.ptr |
| } |
| |
| // CHECK-LABEL: @nonaliased_store: |
| // CHECK: "retval": Constant |
| func.func @nonaliased_store(%arg0: f32) -> f32 { |
| %c1 = llvm.mlir.constant (1) : i64 |
| %ptr = llvm.alloca %c1 x f32 : (i64) -> !llvm.ptr |
| llvm.store %arg0, %ptr : f32, !llvm.ptr |
| |
| %new_ptr = llvm.call @identity(%ptr) : (!llvm.ptr) -> !llvm.ptr |
| %val = llvm.load %new_ptr {tag = "retval"} : !llvm.ptr -> f32 |
| return %val : f32 |
| } |