xref: /llvm-project/mlir/test/Dialect/EmitC/transforms.mlir (revision 977d744b21d06415ac872258bf86e026d8eb487f)
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