1// RUN: mlir-opt %s --form-expressions --verify-diagnostics --split-input-file | FileCheck %s 2 3// CHECK-LABEL: func.func @single_expression( 4// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i32) -> i1 { 5// CHECK: %[[VAL_4:.*]] = "emitc.constant"() <{value = 42 : i32}> : () -> i32 6// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 { 7// CHECK: %[[VAL_6:.*]] = mul %[[VAL_0]], %[[VAL_4]] : (i32, i32) -> i32 8// CHECK: %[[VAL_7:.*]] = sub %[[VAL_6]], %[[VAL_2]] : (i32, i32) -> i32 9// CHECK: %[[VAL_8:.*]] = cmp lt, %[[VAL_7]], %[[VAL_3]] : (i32, i32) -> i1 10// CHECK: yield %[[VAL_8]] : i1 11// CHECK: } 12// CHECK: return %[[VAL_5]] : i1 13// CHECK: } 14 15func.func @single_expression(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i1 { 16 %c42 = "emitc.constant"(){value = 42 : i32} : () -> i32 17 %a = emitc.mul %arg0, %c42 : (i32, i32) -> i32 18 %b = emitc.sub %a, %arg2 : (i32, i32) -> i32 19 %c = emitc.cmp lt, %b, %arg3 :(i32, i32) -> i1 20 return %c : i1 21} 22 23// CHECK-LABEL: func.func @multiple_expressions( 24// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i32) -> (i32, i32) { 25// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 { 26// CHECK: %[[VAL_5:.*]] = mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32 27// CHECK: %[[VAL_6:.*]] = sub %[[VAL_5]], %[[VAL_2]] : (i32, i32) -> i32 28// CHECK: yield %[[VAL_6]] : i32 29// CHECK: } 30// CHECK: %[[VAL_7:.*]] = emitc.expression : i32 { 31// CHECK: %[[VAL_8:.*]] = add %[[VAL_1]], %[[VAL_3]] : (i32, i32) -> i32 32// CHECK: %[[VAL_9:.*]] = div %[[VAL_8]], %[[VAL_2]] : (i32, i32) -> i32 33// CHECK: yield %[[VAL_9]] : i32 34// CHECK: } 35// CHECK: return %[[VAL_4]], %[[VAL_7]] : i32, i32 36// CHECK: } 37 38func.func @multiple_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> (i32, i32) { 39 %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32 40 %b = emitc.sub %a, %arg2 : (i32, i32) -> i32 41 %c = emitc.add %arg1, %arg3 : (i32, i32) -> i32 42 %d = emitc.div %c, %arg2 : (i32, i32) -> i32 43 return %b, %d : i32, i32 44} 45 46// CHECK-LABEL: func.func @expression_with_call( 47// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i32) -> i1 { 48// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 { 49// CHECK: %[[VAL_5:.*]] = mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32 50// CHECK: %[[VAL_6:.*]] = call_opaque "foo"(%[[VAL_5]], %[[VAL_2]]) : (i32, i32) -> i32 51// CHECK: yield %[[VAL_6]] : i32 52// CHECK: } 53// CHECK: %[[VAL_7:.*]] = emitc.expression : i1 { 54// CHECK: %[[VAL_8:.*]] = cmp lt, %[[VAL_4]], %[[VAL_1]] : (i32, i32) -> i1 55// CHECK: yield %[[VAL_8]] : i1 56// CHECK: } 57// CHECK: return %[[VAL_7]] : i1 58// CHECK: } 59 60func.func @expression_with_call(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i1 { 61 %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32 62 %b = emitc.call_opaque "foo" (%a, %arg2) : (i32, i32) -> (i32) 63 %c = emitc.cmp lt, %b, %arg1 :(i32, i32) -> i1 64 return %c : i1 65} 66 67// CHECK-LABEL: func.func @expression_with_dereference( 68// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: !emitc.ptr<i32>) -> i1 { 69// CHECK: %[[VAL_3:.*]] = emitc.expression : i32 { 70// CHECK: %[[VAL_4:.*]] = apply "*"(%[[VAL_2]]) : (!emitc.ptr<i32>) -> i32 71// CHECK: yield %[[VAL_4]] : i32 72// CHECK: } 73// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 { 74// CHECK: %[[VAL_6:.*]] = mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32 75// CHECK: %[[VAL_7:.*]] = cmp lt, %[[VAL_6]], %[[VAL_3]] : (i32, i32) -> i1 76// CHECK: return %[[VAL_5]] : i1 77// CHECK: } 78 79func.func @expression_with_dereference(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 { 80 %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32 81 %b = emitc.apply "*"(%arg2) : (!emitc.ptr<i32>) -> (i32) 82 %c = emitc.cmp lt, %a, %b :(i32, i32) -> i1 83 return %c : i1 84} 85 86 87// CHECK-LABEL: func.func @expression_with_address_taken( 88// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: !emitc.ptr<i32>) -> i1 { 89// CHECK: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32> 90// CHECK: %[[VAL_4:.*]] = emitc.expression : i1 { 91// CHECK: %[[VAL_5:.*]] = apply "&"(%[[VAL_3]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32> 92// CHECK: %[[VAL_6:.*]] = add %[[VAL_5]], %[[VAL_1]] : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32> 93// CHECK: %[[VAL_7:.*]] = cmp lt, %[[VAL_6]], %[[VAL_2]] : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1 94// CHECK: yield %[[VAL_7]] : i1 95// CHECK: } 96// CHECK: return %[[VAL_4]] : i1 97// CHECK: } 98 99func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 { 100 %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32> 101 %a = emitc.apply "&"(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32> 102 %b = emitc.add %a, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32> 103 %c = emitc.cmp lt, %b, %arg2 :(!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1 104 return %c : i1 105} 106 107// CHECK-LABEL: func.func @no_nested_expression( 108// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32) -> i1 { 109// CHECK: %[[VAL_2:.*]] = emitc.expression : i1 { 110// CHECK: %[[VAL_3:.*]] = cmp lt, %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i1 111// CHECK: yield %[[VAL_3]] : i1 112// CHECK: } 113// CHECK: return %[[VAL_2]] : i1 114// CHECK: } 115 116func.func @no_nested_expression(%arg0: i32, %arg1: i32) -> i1 { 117 %a = emitc.expression : i1 { 118 %b = emitc.cmp lt, %arg0, %arg1 :(i32, i32) -> i1 119 emitc.yield %b : i1 120 } 121 return %a : i1 122} 123 124 125// CHECK-LABEL: func.func @single_result_requirement 126// CHECK-NOT: emitc.expression 127 128func.func @single_result_requirement() -> (i32, i32) { 129 %0:2 = emitc.call_opaque "foo" () : () -> (i32, i32) 130 return %0#0, %0#1 : i32, i32 131} 132