194 lines · plain
1// RUN: mlir-opt %s --transform-dialect-check-uses --split-input-file --verify-diagnostics2 3func.func @use_after_free_branching_control_flow() {4 // expected-note @below {{allocated here}}5 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op6 transform.test_transform_op_with_regions {7 "transform.test_branching_transform_op_terminator"() : () -> ()8 },9 {10 ^bb0:11 "transform.test_branching_transform_op_terminator"()[^bb1, ^bb2] : () -> ()12 ^bb1:13 // expected-note @below {{freed here}}14 transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op15 "transform.test_branching_transform_op_terminator"()[^bb3] : () -> ()16 ^bb2:17 "transform.test_branching_transform_op_terminator"()[^bb3] : () -> ()18 ^bb3:19 // expected-warning @below {{operand #0 may be used after free}}20 transform.sequence %0 : !transform.any_op failures(propagate) {21 ^bb0(%arg0: !transform.any_op):22 }23 "transform.test_branching_transform_op_terminator"() : () -> ()24 }25 return26}27 28// -----29 30func.func @use_after_free_in_nested_op() {31 // expected-note @below {{allocated here}}32 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op33 // expected-note @below {{freed here}}34 transform.test_transform_op_with_regions {35 "transform.test_branching_transform_op_terminator"() : () -> ()36 },37 {38 ^bb0:39 "transform.test_branching_transform_op_terminator"()[^bb1, ^bb2] : () -> ()40 ^bb1:41 transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op42 "transform.test_branching_transform_op_terminator"()[^bb3] : () -> ()43 ^bb2:44 "transform.test_branching_transform_op_terminator"()[^bb3] : () -> ()45 ^bb3:46 "transform.test_branching_transform_op_terminator"() : () -> ()47 }48 // expected-warning @below {{operand #0 may be used after free}}49 transform.sequence %0 : !transform.any_op failures(propagate) {50 ^bb0(%arg0: !transform.any_op):51 }52 return53}54 55// -----56 57func.func @use_after_free_recursive_side_effects() {58 transform.sequence failures(propagate) {59 ^bb0(%arg0: !transform.any_op):60 // expected-note @below {{allocated here}}61 %0 = transform.sequence %arg0 : !transform.any_op -> !transform.any_op failures(propagate) attributes { ord = 1 } {62 ^bb1(%arg1: !transform.any_op):63 yield %arg1 : !transform.any_op64 }65 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 2 } {66 ^bb2(%arg2: !transform.any_op):67 }68 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 3 } {69 ^bb3(%arg3: !transform.any_op):70 }71 72 // `transform.sequence` has recursive side effects so it has the same "free"73 // as the child op it contains.74 // expected-note @below {{freed here}}75 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 4 } {76 ^bb4(%arg4: !transform.any_op):77 test_consume_operand_of_op_kind_or_fail %0, "transform.sequence" : !transform.any_op78 }79 // expected-warning @below {{operand #0 may be used after free}}80 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 5 } {81 ^bb3(%arg3: !transform.any_op):82 }83 }84 return85}86 87// -----88 89func.func @use_after_free() {90 transform.sequence failures(propagate) {91 ^bb0(%arg0: !transform.any_op):92 // expected-note @below {{allocated here}}93 %0 = transform.sequence %arg0 : !transform.any_op -> !transform.any_op failures(propagate) attributes { ord = 1 } {94 ^bb1(%arg1: !transform.any_op):95 yield %arg1 : !transform.any_op96 }97 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 2 } {98 ^bb2(%arg2: !transform.any_op):99 }100 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 3 } {101 ^bb3(%arg3: !transform.any_op):102 }103 104 // expected-note @below {{freed here}}105 test_consume_operand_of_op_kind_or_fail %0, "transform.sequence" : !transform.any_op106 // expected-warning @below {{operand #0 may be used after free}}107 transform.sequence %0 : !transform.any_op failures(propagate) attributes { ord = 5 } {108 ^bb3(%arg3: !transform.any_op):109 }110 }111 return112}113 114// -----115 116// In the case of a control flow cycle, the operation that uses the value may117// precede the one that frees it in the same block. Both operations should118// be reported as use-after-free.119func.func @use_after_free_self_cycle() {120 // expected-note @below {{allocated here}}121 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op122 transform.test_transform_op_with_regions {123 "transform.test_branching_transform_op_terminator"() : () -> ()124 },125 {126 ^bb0:127 "transform.test_branching_transform_op_terminator"()[^bb1] : () -> ()128 ^bb1:129 // expected-warning @below {{operand #0 may be used after free}}130 transform.sequence %0 : !transform.any_op failures(propagate) {131 ^bb0(%arg0: !transform.any_op):132 }133 // expected-warning @below {{operand #0 may be used after free}}134 // expected-note @below {{freed here}}135 transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op136 "transform.test_branching_transform_op_terminator"()[^bb1, ^bb2] : () -> ()137 ^bb2:138 "transform.test_branching_transform_op_terminator"() : () -> ()139 }140 return141}142 143 144// -----145 146// Check that the "free" that happens in a cycle is also reported as potential147// use-after-free.148func.func @use_after_free_cycle() {149 // expected-note @below {{allocated here}}150 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op151 transform.test_transform_op_with_regions {152 "transform.test_branching_transform_op_terminator"() : () -> ()153 },154 {155 ^bb0:156 "transform.test_branching_transform_op_terminator"()[^bb1, ^bb2] : () -> ()157 ^bb1:158 // expected-warning @below {{operand #0 may be used after free}}159 // expected-note @below {{freed here}}160 transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op161 "transform.test_branching_transform_op_terminator"()[^bb2, ^bb3] : () -> ()162 ^bb2:163 "transform.test_branching_transform_op_terminator"()[^bb1] : () -> ()164 ^bb3:165 "transform.test_branching_transform_op_terminator"() : () -> ()166 }167 return168}169 170// -----171 172// This should not crash.173 174transform.sequence failures(propagate) {175^bb0(%arg0: !transform.any_op):176 alternatives %arg0 : !transform.any_op {177 ^bb0(%arg1: !transform.any_op):178 }179}180 181// -----182 183// This should not crash.184 185module attributes {transform.with_named_sequence} {186 transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {187 %0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op188 transform.apply_patterns to %0 {189 transform.apply_patterns.memref.extract_address_computations190 } : !transform.any_op191 transform.yield192 }193}194