Skip to content

Commit 0ca2d4d

Browse files
authored
[mlir][emitc] mark emitc.load with CExpression (#130802)
Follow the `call` and `call_opaque` operations, as well as `apply`, which already are marked as `CExpression` even though they have side effects. Even though `emitc.load` can be included inside the `emitc.expression`, the inlining and `--form-expression` pass won't actually inline them inside other expression due to it having a side effect, thus unless the user manually writes the `emitc.load` inside the `emitc.expression` it won't appear there. -- It was brought #91475 (comment) and while there was some opposition due to `load` having a side effect, `emitc` already allows all the rest operations that have it, so for consistency reasons, enabling it doesn't really hurt from my point of view. Especially given that `--form-expression` doesn't allow it to really inline inside other expressions, which makes sense, since if the users want such behavior, they should explicitly opt-in.
1 parent 53927ab commit 0ca2d4d

File tree

4 files changed

+96
-7
lines changed

4 files changed

+96
-7
lines changed

mlir/include/mlir/Dialect/EmitC/IR/EmitC.td

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -489,12 +489,9 @@ def EmitC_ExpressionOp : EmitC_Op<"expression",
489489
auto applyOp = dyn_cast<emitc::ApplyOp>(op);
490490
if (applyOp)
491491
return applyOp.getApplicableOperator() == "*";
492-
// Any operation using variables is assumed to have a side effect of
493-
// reading memory mutable by emitc::assign ops.
494-
return llvm::any_of(op.getOperands(), [](Value operand) {
495-
Operation *def = operand.getDefiningOp();
496-
return def && isa<emitc::VariableOp>(def);
497-
});
492+
// Any load operation is assumed to read from memory and thus perform
493+
// a side effect.
494+
return isa<emitc::LoadOp>(op);
498495
};
499496
return llvm::any_of(getRegion().front().without_terminator(), predicate);
500497
};
@@ -927,7 +924,7 @@ def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", [CExpression]> {
927924
let assemblyFormat = "operands attr-dict `:` type(operands)";
928925
}
929926

930-
def EmitC_LoadOp : EmitC_Op<"load", [
927+
def EmitC_LoadOp : EmitC_Op<"load", [CExpression,
931928
TypesMatchWith<"result type matches value type of 'operand'",
932929
"operand", "result",
933930
"::llvm::cast<LValueType>($_self).getValueType()">

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ static FailureOr<int> getOperatorPrecedence(Operation *operation) {
100100
})
101101
.Case<emitc::ConditionalOp>([&](auto op) { return 2; })
102102
.Case<emitc::DivOp>([&](auto op) { return 13; })
103+
.Case<emitc::LoadOp>([&](auto op) { return 16; })
103104
.Case<emitc::LogicalAndOp>([&](auto op) { return 4; })
104105
.Case<emitc::LogicalNotOp>([&](auto op) { return 15; })
105106
.Case<emitc::LogicalOrOp>([&](auto op) { return 3; })

mlir/test/Dialect/EmitC/transforms.mlir

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,37 @@ func.func @single_result_requirement() -> (i32, i32) {
129129
%0:2 = emitc.call_opaque "foo" () : () -> (i32, i32)
130130
return %0#0, %0#1 : i32, i32
131131
}
132+
133+
// CHECK-LABEL: func.func @expression_with_load(
134+
// CHECK-SAME: %[[VAL_0:.*]]: i32,
135+
// CHECK-SAME: %[[VAL_1:.*]]: !emitc.ptr<i32>) -> i1 {
136+
// CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
137+
// CHECK: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue<i32>
138+
// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 {
139+
// CHECK: %[[VAL_5:.*]] = load %[[VAL_3]] : <i32>
140+
// CHECK: yield %[[VAL_5]] : i32
141+
// CHECK: }
142+
// CHECK: %[[VAL_6:.*]] = emitc.subscript %[[VAL_1]]{{\[}}%[[VAL_2]]] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
143+
// CHECK: %[[VAL_7:.*]] = emitc.expression : i32 {
144+
// CHECK: %[[VAL_8:.*]] = load %[[VAL_6]] : <i32>
145+
// CHECK: yield %[[VAL_8]] : i32
146+
// CHECK: }
147+
// CHECK: %[[VAL_9:.*]] = emitc.expression : i1 {
148+
// CHECK: %[[VAL_10:.*]] = add %[[VAL_4]], %[[VAL_7]] : (i32, i32) -> i32
149+
// CHECK: %[[VAL_11:.*]] = cmp lt, %[[VAL_10]], %[[VAL_0]] : (i32, i32) -> i1
150+
// CHECK: yield %[[VAL_11]] : i1
151+
// CHECK: }
152+
// CHECK: return %[[VAL_9]] : i1
153+
// CHECK: }
154+
155+
156+
func.func @expression_with_load(%arg0: i32, %arg1: !emitc.ptr<i32>) -> i1 {
157+
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
158+
%0 = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue<i32>
159+
%a = emitc.load %0 : !emitc.lvalue<i32>
160+
%ptr = emitc.subscript %arg1[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
161+
%ptr_load = emitc.load %ptr : !emitc.lvalue<i32>
162+
%b = emitc.add %a, %ptr_load : (i32, i32) -> i32
163+
%c = emitc.cmp lt, %b, %arg0 :(i32, i32) -> i1
164+
return %c : i1
165+
}

mlir/test/Target/Cpp/expressions.mlir

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,60 @@ func.func @expression_with_subscript_user(%arg0: !emitc.ptr<!emitc.opaque<"void"
342342
%res_load = emitc.load %res : !emitc.lvalue<i32>
343343
return %res_load : i32
344344
}
345+
346+
// CPP-DEFAULT: bool expression_with_load(int32_t [[VAL_1:v.+]], int32_t [[VAL_2:v.+]], int32_t* [[VAL_3:v.+]]) {
347+
// CPP-DEFAULT-NEXT: int64_t [[VAL_4:v.+]] = 0;
348+
// CPP-DEFAULT-NEXT: int32_t [[VAL_5:v.+]] = 42;
349+
// CPP-DEFAULT-NEXT: bool [[VAL_6:v.+]] = [[VAL_5]] + [[VAL_2]] < [[VAL_3]][[[VAL_4]]] + [[VAL_1]];
350+
// CPP-DEFAULT-NEXT: return [[VAL_6]];
351+
352+
// CPP-DECLTOP: bool expression_with_load(int32_t [[VAL_1:v.+]], int32_t [[VAL_2:v.+]], int32_t* [[VAL_3:v.+]]) {
353+
// CPP-DECLTOP-NEXT: int64_t [[VAL_4:v.+]];
354+
// CPP-DECLTOP-NEXT: int32_t [[VAL_5:v.+]];
355+
// CPP-DECLTOP-NEXT: bool [[VAL_6:v.+]];
356+
// CPP-DECLTOP-NEXT: [[VAL_4]] = 0;
357+
// CPP-DECLTOP-NEXT: [[VAL_5]] = 42;
358+
// CPP-DECLTOP-NEXT: [[VAL_6]] = [[VAL_5]] + [[VAL_2]] < [[VAL_3]][[[VAL_4]]] + [[VAL_1]];
359+
// CPP-DECLTOP-NEXT: return [[VAL_6]];
360+
361+
func.func @expression_with_load(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
362+
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
363+
%0 = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue<i32>
364+
%ptr = emitc.subscript %arg2[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
365+
%result = emitc.expression : i1 {
366+
%a = emitc.load %0 : !emitc.lvalue<i32>
367+
%b = emitc.add %a, %arg1 : (i32, i32) -> i32
368+
%c = emitc.load %ptr : !emitc.lvalue<i32>
369+
%d = emitc.add %c, %arg0 : (i32, i32) -> i32
370+
%e = emitc.cmp lt, %b, %d :(i32, i32) -> i1
371+
yield %e : i1
372+
}
373+
return %result : i1
374+
}
375+
376+
// CPP-DEFAULT: bool expression_with_load_and_call(int32_t* [[VAL_1:v.+]]) {
377+
// CPP-DEFAULT-NEXT: int64_t [[VAL_2:v.+]] = 0;
378+
// CPP-DEFAULT-NEXT: bool [[VAL_3:v.+]] = [[VAL_1]][[[VAL_2]]] + bar([[VAL_1]][[[VAL_2]]]) < [[VAL_1]][[[VAL_2]]];
379+
// CPP-DEFAULT-NEXT: return [[VAL_3]];
380+
381+
// CPP-DECLTOP: bool expression_with_load_and_call(int32_t* [[VAL_1:v.+]]) {
382+
// CPP-DECLTOP-NEXT: int64_t [[VAL_2:v.+]];
383+
// CPP-DECLTOP-NEXT: bool [[VAL_3:v.+]];
384+
// CPP-DECLTOP-NEXT: [[VAL_2]] = 0;
385+
// CPP-DECLTOP-NEXT: [[VAL_3]] = [[VAL_1]][[[VAL_2]]] + bar([[VAL_1]][[[VAL_2]]]) < [[VAL_1]][[[VAL_2]]];
386+
// CPP-DECLTOP-NEXT: return [[VAL_3]];
387+
388+
func.func @expression_with_load_and_call(%arg0: !emitc.ptr<i32>) -> i1 {
389+
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
390+
%ptr = emitc.subscript %arg0[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
391+
%result = emitc.expression : i1 {
392+
%a = emitc.load %ptr : !emitc.lvalue<i32>
393+
%b = emitc.load %ptr : !emitc.lvalue<i32>
394+
%c = emitc.load %ptr : !emitc.lvalue<i32>
395+
%d = emitc.call_opaque "bar" (%a) : (i32) -> (i32)
396+
%e = add %c, %d : (i32, i32) -> i32
397+
%f = emitc.cmp lt, %e, %b :(i32, i32) -> i1
398+
yield %f : i1
399+
}
400+
return %result : i1
401+
}

0 commit comments

Comments
 (0)