xref: /llvm-project/mlir/test/Target/Cpp/expressions.mlir (revision e47b507562624bf291ab2515699d39c2669b6131)
1// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT
2// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s -check-prefix=CPP-DECLTOP
3
4// CPP-DEFAULT:      int32_t single_use(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
5// CPP-DEFAULT-NEXT:   bool [[VAL_5:v[0-9]+]] = bar([[VAL_1]] * M_PI, [[VAL_3]]) - [[VAL_4]] < [[VAL_2]];
6// CPP-DEFAULT-NEXT:   int32_t [[VAL_6:v[0-9]+]];
7// CPP-DEFAULT-NEXT:   if ([[VAL_5]]) {
8// CPP-DEFAULT-NEXT:     [[VAL_6]] = [[VAL_1]];
9// CPP-DEFAULT-NEXT:   } else {
10// CPP-DEFAULT-NEXT:     [[VAL_6]] = [[VAL_1]];
11// CPP-DEFAULT-NEXT:   }
12// CPP-DEFAULT-NEXT:   int32_t [[VAL_7:v[0-9]+]] = [[VAL_6]];
13// CPP-DEFAULT-NEXT:   return [[VAL_7]];
14// CPP-DEFAULT-NEXT: }
15
16// CPP-DECLTOP:      int32_t single_use(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
17// CPP-DECLTOP-NEXT:   bool [[VAL_5:v[0-9]+]];
18// CPP-DECLTOP-NEXT:   int32_t [[VAL_6:v[0-9]+]];
19// CPP-DECLTOP-NEXT:   int32_t [[VAL_7:v[0-9]+]];
20// CPP-DECLTOP-NEXT:   [[VAL_5]] = bar([[VAL_1]] * M_PI, [[VAL_3]]) - [[VAL_4]] < [[VAL_2]];
21// CPP-DECLTOP-NEXT:   ;
22// CPP-DECLTOP-NEXT:   if ([[VAL_5]]) {
23// CPP-DECLTOP-NEXT:     [[VAL_6]] = [[VAL_1]];
24// CPP-DECLTOP-NEXT:   } else {
25// CPP-DECLTOP-NEXT:     [[VAL_6]] = [[VAL_1]];
26// CPP-DECLTOP-NEXT:   }
27// CPP-DECLTOP-NEXT:   [[VAL_7]] = [[VAL_6]];
28// CPP-DECLTOP-NEXT:   return [[VAL_7]];
29// CPP-DECLTOP-NEXT: }
30
31func.func @single_use(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
32  %p0 = emitc.literal "M_PI" : i32
33  %e = emitc.expression : i1 {
34    %a = emitc.mul %arg0, %p0 : (i32, i32) -> i32
35    %b = emitc.call_opaque "bar" (%a, %arg2) : (i32, i32) -> (i32)
36    %c = emitc.sub %b, %arg3 : (i32, i32) -> i32
37    %d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
38    emitc.yield %d : i1
39  }
40  %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
41  emitc.if %e {
42    emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
43    emitc.yield
44  } else {
45    emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
46    emitc.yield
47  }
48  %v_load = emitc.load %v : !emitc.lvalue<i32>
49  return %v_load : i32
50}
51
52// CPP-DEFAULT: int32_t do_not_inline(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
53// CPP-DEFAULT-NEXT: int32_t [[VAL_4:v[0-9]+]] = ([[VAL_1]] + [[VAL_2]]) * [[VAL_3]];
54// CPP-DEFAULT-NEXT: return [[VAL_4]];
55// CPP-DEFAULT-NEXT:}
56
57// CPP-DECLTOP: int32_t do_not_inline(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
58// CPP-DECLTOP-NEXT: int32_t [[VAL_4:v[0-9]+]];
59// CPP-DECLTOP-NEXT: [[VAL_4]] = ([[VAL_1]] + [[VAL_2]]) * [[VAL_3]];
60// CPP-DECLTOP-NEXT: return [[VAL_4]];
61// CPP-DECLTOP-NEXT:}
62
63func.func @do_not_inline(%arg0: i32, %arg1: i32, %arg2 : i32) -> i32 {
64  %e = emitc.expression noinline : i32 {
65    %a = emitc.add %arg0, %arg1 : (i32, i32) -> i32
66    %b = emitc.mul %a, %arg2 : (i32, i32) -> i32
67    emitc.yield %b : i32
68  }
69  return %e : i32
70}
71
72// CPP-DEFAULT:      float parentheses_for_low_precedence(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
73// CPP-DEFAULT-NEXT:   return (float) ([[VAL_1]] + [[VAL_2]] * [[VAL_3]]);
74// CPP-DEFAULT-NEXT: }
75
76// CPP-DECLTOP:      float parentheses_for_low_precedence(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
77// CPP-DECLTOP-NEXT:   return (float) ([[VAL_1]] + [[VAL_2]] * [[VAL_3]]);
78// CPP-DECLTOP-NEXT: }
79
80func.func @parentheses_for_low_precedence(%arg0: i32, %arg1: i32, %arg2: i32) -> f32 {
81  %e = emitc.expression : f32 {
82    %a = emitc.add %arg0, %arg1 : (i32, i32) -> i32
83    %b = emitc.mul %a, %arg2 : (i32, i32) -> i32
84    %d = emitc.cast %b : i32 to f32
85    emitc.yield %d : f32
86  }
87  return %e : f32
88}
89
90// CPP-DEFAULT:      int32_t parentheses_for_same_precedence(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
91// CPP-DEFAULT-NEXT:   return [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
92// CPP-DEFAULT-NEXT: }
93
94// CPP-DECLTOP:      int32_t parentheses_for_same_precedence(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
95// CPP-DECLTOP-NEXT:   return [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
96// CPP-DECLTOP-NEXT: }
97func.func @parentheses_for_same_precedence(%arg0: i32, %arg1: i32, %arg2: i32) -> i32 {
98  %e = emitc.expression : i32 {
99      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
100      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
101      emitc.yield %1 : i32
102    }
103
104  return %e : i32
105}
106
107// CPP-DEFAULT:      int32_t user_with_expression_trait(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
108// CPP-DEFAULT-NEXT:   int32_t [[VAL_4:v[0-9]+]] = 0;
109// CPP-DEFAULT-NEXT:   int32_t [[EXP_0:v[0-9]+]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
110// CPP-DEFAULT-NEXT:   int32_t [[EXP_1:v[0-9]+]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
111// CPP-DEFAULT-NEXT:   int32_t [[EXP_2:v[0-9]+]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
112// CPP-DEFAULT-NEXT:   int32_t [[EXP_3:v[0-9]+]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
113// CPP-DEFAULT-NEXT:   bool [[CAST:v[0-9]+]] = (bool) [[EXP_0]];
114// CPP-DEFAULT-NEXT:   int32_t [[ADD:v[0-9]+]] = [[EXP_1]] + [[VAL_4]];
115// CPP-DEFAULT-NEXT:   int32_t [[CALL:v[0-9]+]] = bar([[EXP_2]], [[VAL_4]]);
116// CPP-DEFAULT-NEXT:   int32_t [[COND:v[0-9]+]] = [[CAST]] ? [[EXP_3]] : [[VAL_4]];
117// CPP-DEFAULT-NEXT:   int32_t [[VAR:v[0-9]+]];
118// CPP-DEFAULT-NEXT:   [[VAR]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
119// CPP-DEFAULT-NEXT:   return [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
120// CPP-DEFAULT-NEXT: }
121
122// CPP-DECLTOP:      int32_t user_with_expression_trait(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
123// CPP-DECLTOP-NEXT:   int32_t [[VAL_4:v[0-9]+]];
124// CPP-DECLTOP-NEXT:   int32_t [[EXP_0:v[0-9]+]];
125// CPP-DECLTOP-NEXT:   int32_t [[EXP_1:v[0-9]+]];
126// CPP-DECLTOP-NEXT:   int32_t [[EXP_2:v[0-9]+]];
127// CPP-DECLTOP-NEXT:   int32_t [[EXP_3:v[0-9]+]];
128// CPP-DECLTOP-NEXT:   bool [[CAST:v[0-9]+]];
129// CPP-DECLTOP-NEXT:   int32_t [[ADD:v[0-9]+]];
130// CPP-DECLTOP-NEXT:   int32_t [[CALL:v[0-9]+]];
131// CPP-DECLTOP-NEXT:   int32_t [[COND:v[0-9]+]];
132// CPP-DECLTOP-NEXT:   int32_t [[VAR:v[0-9]+]];
133// CPP-DECLTOP-NEXT:   [[VAL_4]] = 0;
134// CPP-DECLTOP-NEXT:   [[EXP_0]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
135// CPP-DECLTOP-NEXT:   [[EXP_1]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
136// CPP-DECLTOP-NEXT:   [[EXP_2]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
137// CPP-DECLTOP-NEXT:   [[EXP_3]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
138// CPP-DECLTOP-NEXT:   [[CAST]] = (bool) [[EXP_0]];
139// CPP-DECLTOP-NEXT:   [[ADD]] = [[EXP_1]] + [[VAL_4]];
140// CPP-DECLTOP-NEXT:   [[CALL]] = bar([[EXP_2]], [[VAL_4]]);
141// CPP-DECLTOP-NEXT:   [[COND]] = [[CAST]] ? [[EXP_3]] : [[VAL_4]];
142// CPP-DECLTOP-NEXT:   ;
143// CPP-DECLTOP-NEXT:   [[VAR]] = [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
144// CPP-DECLTOP-NEXT:   return [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
145// CPP-DECLTOP-NEXT: }
146func.func @user_with_expression_trait(%arg0: i32, %arg1: i32, %arg2: i32) -> i32 {
147  %c0 = "emitc.constant"() {value = 0 : i32} : () -> i32
148  %e0 = emitc.expression : i32 {
149      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
150      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
151      emitc.yield %1 : i32
152    }
153  %e1 = emitc.expression : i32 {
154      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
155      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
156      emitc.yield %1 : i32
157    }
158  %e2 = emitc.expression : i32 {
159      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
160      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
161      emitc.yield %1 : i32
162    }
163  %e3 = emitc.expression : i32 {
164      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
165      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
166      emitc.yield %1 : i32
167    }
168  %e4 = emitc.expression : i32 {
169      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
170      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
171      emitc.yield %1 : i32
172    }
173  %e5 = emitc.expression : i32 {
174      %0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
175      %1 = emitc.div %arg2, %0 : (i32, i32) -> i32
176      emitc.yield %1 : i32
177    }
178  %cast = emitc.cast %e0 : i32 to i1
179  %add = emitc.add %e1, %c0 : (i32, i32) -> i32
180  %call = emitc.call_opaque "bar" (%e2, %c0) : (i32, i32) -> (i32)
181  %cond = emitc.conditional %cast, %e3, %c0 : i32
182  %var = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
183  emitc.assign %e4 : i32 to %var : !emitc.lvalue<i32>
184  return %e5 : i32
185}
186
187// CPP-DEFAULT:      int32_t multiple_uses(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
188// CPP-DEFAULT-NEXT:   bool [[VAL_5:v[0-9]+]] = bar([[VAL_1]] * [[VAL_2]], [[VAL_3]]) - [[VAL_4]] < [[VAL_2]];
189// CPP-DEFAULT-NEXT:   int32_t [[VAL_6:v[0-9]+]];
190// CPP-DEFAULT-NEXT:   if ([[VAL_5]]) {
191// CPP-DEFAULT-NEXT:     [[VAL_6]] = [[VAL_1]];
192// CPP-DEFAULT-NEXT:   } else {
193// CPP-DEFAULT-NEXT:     [[VAL_6]] = [[VAL_1]];
194// CPP-DEFAULT-NEXT:   }
195// CPP-DEFAULT-NEXT:   bool [[VAL_7:v[0-9]+]];
196// CPP-DEFAULT-NEXT:   [[VAL_7]] = [[VAL_5]];
197// CPP-DEFAULT-NEXT:   int32_t [[VAL_8:v[0-9]+]] = [[VAL_6]];
198// CPP-DEFAULT-NEXT:   return [[VAL_8]];
199// CPP-DEFAULT-NEXT: }
200
201// CPP-DECLTOP:      int32_t multiple_uses(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
202// CPP-DECLTOP-NEXT:   bool [[VAL_5:v[0-9]+]];
203// CPP-DECLTOP-NEXT:   int32_t [[VAL_6:v[0-9]+]];
204// CPP-DECLTOP-NEXT:   bool [[VAL_7:v[0-9]+]];
205// CPP-DECLTOP-NEXT:   int32_t [[VAL_8:v[0-9]+]];
206// CPP-DECLTOP-NEXT:   [[VAL_5]] = bar([[VAL_1]] * [[VAL_2]], [[VAL_3]]) - [[VAL_4]] < [[VAL_2]];
207// CPP-DECLTOP-NEXT:   ;
208// CPP-DECLTOP-NEXT:   if ([[VAL_5]]) {
209// CPP-DECLTOP-NEXT:     [[VAL_6]] = [[VAL_1]];
210// CPP-DECLTOP-NEXT:   } else {
211// CPP-DECLTOP-NEXT:     [[VAL_6]] = [[VAL_1]];
212// CPP-DECLTOP-NEXT:   }
213// CPP-DECLTOP-NEXT:   ;
214// CPP-DECLTOP-NEXT:   [[VAL_7]] = [[VAL_5]];
215// CPP-DECLTOP-NEXT:   [[VAL_8]] = [[VAL_6]];
216// CPP-DECLTOP-NEXT:   return [[VAL_8]];
217// CPP-DECLTOP-NEXT: }
218
219func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
220  %e = emitc.expression : i1 {
221    %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
222    %b = emitc.call_opaque "bar" (%a, %arg2) : (i32, i32) -> (i32)
223    %c = emitc.sub %b, %arg3 : (i32, i32) -> i32
224    %d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
225    emitc.yield %d : i1
226  }
227  %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
228  emitc.if %e {
229    emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
230    emitc.yield
231  } else {
232    emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
233    emitc.yield
234  }
235  %q = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i1>
236  emitc.assign %e : i1 to %q : !emitc.lvalue<i1>
237  %v_load = emitc.load %v : !emitc.lvalue<i32>
238  return %v_load : i32
239}
240
241// CPP-DEFAULT:      int32_t different_expressions(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
242// CPP-DEFAULT-NEXT:   int32_t [[VAL_5:v[0-9]+]] = [[VAL_3]] % [[VAL_4]];
243// CPP-DEFAULT-NEXT:   int32_t [[VAL_6:v[0-9]+]] = bar([[VAL_5]], [[VAL_1]] * [[VAL_2]]);
244// CPP-DEFAULT-NEXT:   int32_t [[VAL_7:v[0-9]+]];
245// CPP-DEFAULT-NEXT:   if ([[VAL_6]] - [[VAL_4]] < [[VAL_2]]) {
246// CPP-DEFAULT-NEXT:     [[VAL_7]] = [[VAL_1]];
247// CPP-DEFAULT-NEXT:   } else {
248// CPP-DEFAULT-NEXT:     [[VAL_7]] = [[VAL_1]];
249// CPP-DEFAULT-NEXT:   }
250// CPP-DEFAULT-NEXT:   int32_t [[VAL_8:v[0-9]+]] = [[VAL_7]];
251// CPP-DEFAULT-NEXT:   return [[VAL_8]];
252// CPP-DEFAULT-NEXT: }
253
254// CPP-DECLTOP:      int32_t different_expressions(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
255// CPP-DECLTOP-NEXT:   int32_t [[VAL_5:v[0-9]+]];
256// CPP-DECLTOP-NEXT:   int32_t [[VAL_6:v[0-9]+]];
257// CPP-DECLTOP-NEXT:   int32_t [[VAL_7:v[0-9]+]];
258// CPP-DECLTOP-NEXT:   int32_t [[VAL_8:v[0-9]+]];
259// CPP-DECLTOP-NEXT:   [[VAL_5]] = [[VAL_3]] % [[VAL_4]];
260// CPP-DECLTOP-NEXT:   [[VAL_6]] = bar([[VAL_5]], [[VAL_1]] * [[VAL_2]]);
261// CPP-DECLTOP-NEXT:   ;
262// CPP-DECLTOP-NEXT:   if ([[VAL_6]] - [[VAL_4]] < [[VAL_2]]) {
263// CPP-DECLTOP-NEXT:     [[VAL_7]] = [[VAL_1]];
264// CPP-DECLTOP-NEXT:   } else {
265// CPP-DECLTOP-NEXT:     [[VAL_7]] = [[VAL_1]];
266// CPP-DECLTOP-NEXT:   }
267// CPP-DECLTOP-NEXT:   [[VAL_8]] = [[VAL_7]];
268// CPP-DECLTOP-NEXT:   return [[VAL_8]];
269// CPP-DECLTOP-NEXT: }
270
271func.func @different_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
272  %e1 = emitc.expression : i32 {
273    %a = emitc.rem %arg2, %arg3 : (i32, i32) -> i32
274    emitc.yield %a : i32
275  }
276  %e2 = emitc.expression : i32 {
277    %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
278    %b = emitc.call_opaque "bar" (%e1, %a) : (i32, i32) -> (i32)
279    emitc.yield %b : i32
280  }
281  %e3 = emitc.expression : i1 {
282    %c = emitc.sub %e2, %arg3 : (i32, i32) -> i32
283    %d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
284    emitc.yield %d : i1
285  }
286  %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
287  emitc.if %e3 {
288    emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
289    emitc.yield
290  } else {
291    emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
292    emitc.yield
293  }
294  %v_load = emitc.load %v : !emitc.lvalue<i32>
295  return %v_load : i32
296}
297
298// CPP-DEFAULT:      bool expression_with_address_taken(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) {
299// CPP-DEFAULT-NEXT:   int32_t [[VAL_4:v[0-9]+]] = 42;
300// CPP-DEFAULT-NEXT:   return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]];
301// CPP-DEFAULT-NEXT: }
302
303// CPP-DECLTOP:      bool expression_with_address_taken(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) {
304// CPP-DECLTOP-NEXT:   int32_t [[VAL_4:v[0-9]+]];
305// CPP-DECLTOP-NEXT:   [[VAL_4]] = 42;
306// CPP-DECLTOP-NEXT:   return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]];
307// CPP-DECLTOP-NEXT: }
308
309func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
310  %a = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue<i32>
311  %c = emitc.expression : i1 {
312    %d = emitc.apply "&"(%a) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
313    %e = emitc.sub %d, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
314    %f = emitc.cmp lt, %e, %arg2 : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
315    emitc.yield %f : i1
316  }
317  return %c : i1
318}
319
320// CPP-DEFAULT: int32_t expression_with_subscript_user(void* [[VAL_1:v.+]])
321// CPP-DEFAULT-NEXT:   int64_t [[VAL_2:v.+]] = 0;
322// CPP-DEFAULT-NEXT:   int32_t* [[VAL_3:v.+]] = (int32_t*) [[VAL_1]];
323// CPP-DEFAULT-NEXT:   int32_t [[VAL_4:v.+]] = [[VAL_3]][[[VAL_2]]];
324// CPP-DEFAULT-NEXT:   return [[VAL_4]];
325
326// CPP-DECLTOP: int32_t expression_with_subscript_user(void* [[VAL_1:v.+]])
327// CPP-DECLTOP-NEXT:   int64_t [[VAL_2:v.+]];
328// CPP-DECLTOP-NEXT:   int32_t* [[VAL_3:v.+]];
329// CPP-DECLTOP-NEXT:   int32_t [[VAL_4:v.+]];
330// CPP-DECLTOP-NEXT:   [[VAL_2]] = 0;
331// CPP-DECLTOP-NEXT:   [[VAL_3]] = (int32_t*) [[VAL_1]];
332// CPP-DECLTOP-NEXT:   [[VAL_4]] = [[VAL_3]][[[VAL_2]]];
333// CPP-DECLTOP-NEXT:   return [[VAL_4]];
334
335func.func @expression_with_subscript_user(%arg0: !emitc.ptr<!emitc.opaque<"void">>) -> i32 {
336  %c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
337  %0 = emitc.expression : !emitc.ptr<i32> {
338    %0 = emitc.cast %arg0 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
339    emitc.yield %0 : !emitc.ptr<i32>
340  }
341  %res = emitc.subscript %0[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
342  %res_load = emitc.load %res : !emitc.lvalue<i32>
343  return %res_load : i32
344}
345