-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[mlir][emitc] Inline constant when translate #143485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This pr makes one used constant inlined during translation to cpp. Trying to make the generated cpp code more readable.
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-mlir-emitc Author: Jianjian Guan (jacquesguan) ChangesThis pr makes one used constant inlined during translation to cpp. Trying to make the generated cpp code more readable. Patch is 30.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143485.diff 5 Files Affected:
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 5abc112ab8c7a..028fc007fb012 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -334,6 +334,24 @@ static bool shouldBeInlined(ExpressionOp expressionOp) {
return !user->hasTrait<OpTrait::emitc::CExpression>();
}
+/// Determine whether constant \p constantOp should be emitted inline, i.e.
+/// as part of its user. This function Only inline constant with one use.
+static bool shouldBeInlined(ConstantOp constantOp) {
+ // Do not inline expressions with multiple uses.
+ Value result = constantOp.getResult();
+ if (!result.hasOneUse())
+ return false;
+
+ Operation *user = *result.getUsers().begin();
+
+ // Do not inline expressions used by operations with deferred emission, since
+ // their translation requires the materialization of variables.
+ if (hasDeferredEmission(user))
+ return false;
+
+ return true;
+}
+
static LogicalResult printConstantOp(CppEmitter &emitter, Operation *operation,
Attribute value) {
OpResult result = operation->getResult(0);
@@ -368,6 +386,9 @@ static LogicalResult printConstantOp(CppEmitter &emitter, Operation *operation,
static LogicalResult printOperation(CppEmitter &emitter,
emitc::ConstantOp constantOp) {
+ if (shouldBeInlined(constantOp))
+ return success();
+
Operation *operation = constantOp.getOperation();
Attribute value = constantOp.getValue();
@@ -1454,6 +1475,11 @@ LogicalResult CppEmitter::emitOperand(Value value) {
if (expressionOp && shouldBeInlined(expressionOp))
return emitExpression(expressionOp);
+ auto constantOp = dyn_cast_if_present<ConstantOp>(value.getDefiningOp());
+ if (constantOp && shouldBeInlined(constantOp)) {
+ return emitAttribute(constantOp.getLoc(), constantOp.getValue());
+ }
+
os << getOrCreateName(value);
return success();
}
@@ -1650,7 +1676,9 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
if (getEmittedExpression() ||
(isa<emitc::ExpressionOp>(op) &&
- shouldBeInlined(cast<emitc::ExpressionOp>(op))))
+ shouldBeInlined(cast<emitc::ExpressionOp>(op))) ||
+ (isa<emitc::ConstantOp>(op) &&
+ shouldBeInlined(cast<emitc::ConstantOp>(op))))
return success();
// Never emit a semicolon for some operations, especially if endening with
diff --git a/mlir/test/Target/Cpp/for.mlir b/mlir/test/Target/Cpp/for.mlir
index 7cd3d5d646da6..d49a1379b2716 100644
--- a/mlir/test/Target/Cpp/for.mlir
+++ b/mlir/test/Target/Cpp/for.mlir
@@ -63,18 +63,13 @@ func.func @test_for_yield() {
return
}
// CPP-DEFAULT: void test_for_yield() {
-// CPP-DEFAULT-NEXT: size_t [[START:[^ ]*]] = 0;
-// CPP-DEFAULT-NEXT: size_t [[STOP:[^ ]*]] = 10;
-// CPP-DEFAULT-NEXT: size_t [[STEP:[^ ]*]] = 1;
-// CPP-DEFAULT-NEXT: int32_t [[S0:[^ ]*]] = 0;
-// CPP-DEFAULT-NEXT: float [[P0:[^ ]*]] = 1.000000000e+00f;
// CPP-DEFAULT-NEXT: int32_t [[SE:[^ ]*]];
// CPP-DEFAULT-NEXT: float [[PE:[^ ]*]];
// CPP-DEFAULT-NEXT: int32_t [[SI:[^ ]*]];
// CPP-DEFAULT-NEXT: float [[PI:[^ ]*]];
-// CPP-DEFAULT-NEXT: [[SI:[^ ]*]] = [[S0]];
-// CPP-DEFAULT-NEXT: [[PI:[^ ]*]] = [[P0]];
-// CPP-DEFAULT-NEXT: for (size_t [[ITER:[^ ]*]] = [[START]]; [[ITER]] < [[STOP]]; [[ITER]] += [[STEP]]) {
+// CPP-DEFAULT-NEXT: [[SI:[^ ]*]] = 0;
+// CPP-DEFAULT-NEXT: [[PI:[^ ]*]] = 1.000000000e+00f;
+// CPP-DEFAULT-NEXT: for (size_t [[ITER:[^ ]*]] = 0; [[ITER]] < 10; [[ITER]] += 1) {
// CPP-DEFAULT-NEXT: int32_t [[SI_LOAD:[^ ]*]] = [[SI]];
// CPP-DEFAULT-NEXT: int32_t [[SN:[^ ]*]] = add([[SI_LOAD]], [[ITER]]);
// CPP-DEFAULT-NEXT: float [[PI_LOAD:[^ ]*]] = [[PI]];
@@ -104,18 +99,13 @@ func.func @test_for_yield() {
// CPP-DECLTOP-NEXT: float [[PN:[^ ]*]];
// CPP-DECLTOP-NEXT: int32_t [[SI_LOAD2:[^ ]*]];
// CPP-DECLTOP-NEXT: float [[PI_LOAD2:[^ ]*]];
-// CPP-DECLTOP-NEXT: [[START]] = 0;
-// CPP-DECLTOP-NEXT: [[STOP]] = 10;
-// CPP-DECLTOP-NEXT: [[STEP]] = 1;
-// CPP-DECLTOP-NEXT: [[S0]] = 0;
-// CPP-DECLTOP-NEXT: [[P0]] = 1.000000000e+00f;
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: ;
-// CPP-DECLTOP-NEXT: [[SI]] = [[S0]];
-// CPP-DECLTOP-NEXT: [[PI]] = [[P0]];
-// CPP-DECLTOP-NEXT: for (size_t [[ITER:[^ ]*]] = [[START]]; [[ITER]] < [[STOP]]; [[ITER]] += [[STEP]]) {
+// CPP-DECLTOP-NEXT: [[SI]] = 0;
+// CPP-DECLTOP-NEXT: [[PI]] = 1.000000000e+00f;
+// CPP-DECLTOP-NEXT: for (size_t [[ITER:[^ ]*]] = 0; [[ITER]] < 10; [[ITER]] += 1) {
// CPP-DECLTOP-NEXT: [[SI_LOAD]] = [[SI]];
// CPP-DECLTOP-NEXT: [[SN]] = add([[SI_LOAD]], [[ITER]]);
// CPP-DECLTOP-NEXT: [[PI_LOAD]] = [[PI]];
diff --git a/mlir/test/Target/Cpp/lvalue.mlir b/mlir/test/Target/Cpp/lvalue.mlir
index 2aa438eb6371c..0581c514a447b 100644
--- a/mlir/test/Target/Cpp/lvalue.mlir
+++ b/mlir/test/Target/Cpp/lvalue.mlir
@@ -19,8 +19,7 @@ emitc.func @lvalue_variables(%v1: i32, %v2: i32) -> i32 {
// CHECK-NEXT: int32_t* [[VAR_PTR:[^ ]*]] = &[[VAR]];
// CHECK-NEXT: zero([[VAR_PTR]]);
// CHECK-NEXT: int32_t [[VAR_LOAD:[^ ]*]] = [[VAR]];
-// CHECK-NEXT: int32_t [[NEG_ONE:[^ ]*]] = -1;
-// CHECK-NEXT: [[VAR]] = [[NEG_ONE]];
+// CHECK-NEXT: [[VAR]] = -1;
// CHECK-NEXT: return [[VAR_LOAD]];
diff --git a/mlir/test/Target/Cpp/stdops.mlir b/mlir/test/Target/Cpp/stdops.mlir
index 589e5f2e96aff..235caa01033c2 100644
--- a/mlir/test/Target/Cpp/stdops.mlir
+++ b/mlir/test/Target/Cpp/stdops.mlir
@@ -44,13 +44,11 @@ func.func @one_result() -> i32 {
return %0 : i32
}
// CPP-DEFAULT: int32_t one_result() {
-// CPP-DEFAULT-NEXT: int32_t [[V0:[^ ]*]] = 0;
-// CPP-DEFAULT-NEXT: return [[V0]];
+// CPP-DEFAULT-NEXT: return 0;
// CPP-DECLTOP: int32_t one_result() {
// CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]];
-// CPP-DECLTOP-NEXT: [[V0]] = 0;
-// CPP-DECLTOP-NEXT: return [[V0]];
+// CPP-DECLTOP-NEXT: return 0;
func.func @two_results() -> (i32, f32) {
@@ -59,16 +57,12 @@ func.func @two_results() -> (i32, f32) {
return %0, %1 : i32, f32
}
// CPP-DEFAULT: std::tuple<int32_t, float> two_results() {
-// CPP-DEFAULT: int32_t [[V0:[^ ]*]] = 0;
-// CPP-DEFAULT: float [[V1:[^ ]*]] = 1.000000000e+00f;
-// CPP-DEFAULT: return std::make_tuple([[V0]], [[V1]]);
+// CPP-DEFAULT: return std::make_tuple(0, 1.000000000e+00f);
// CPP-DECLTOP: std::tuple<int32_t, float> two_results() {
// CPP-DECLTOP: int32_t [[V0:[^ ]*]];
// CPP-DECLTOP: float [[V1:[^ ]*]];
-// CPP-DECLTOP: [[V0]] = 0;
-// CPP-DECLTOP: [[V1]] = 1.000000000e+00f;
-// CPP-DECLTOP: return std::make_tuple([[V0]], [[V1]]);
+// CPP-DECLTOP: return std::make_tuple(0, 1.000000000e+00f);
func.func @single_return_statement(%arg0 : i32) -> i32 {
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 4e20c1fc6536a..70c35c28a3bc4 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -2,32 +2,30 @@
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck --match-full-lines %s -check-prefix=CPP-DECLTOP
// CPP-DEFAULT-LABEL: void emitc_switch_ptrdiff_t() {
-// CPP-DEFAULT: ptrdiff_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
// CPP-DEFAULT: }
+
// CPP-DECLTOP-LABEL: void emitc_switch_ptrdiff_t() {
// CPP-DECLTOP: ptrdiff_t v1;
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -37,8 +35,7 @@
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -63,20 +60,17 @@ func.func @emitc_switch_ptrdiff_t() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_ssize_t() {
-// CPP-DEFAULT: ssize_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -88,8 +82,7 @@ func.func @emitc_switch_ptrdiff_t() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -99,8 +92,7 @@ func.func @emitc_switch_ptrdiff_t() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -126,20 +118,18 @@ func.func @emitc_switch_ssize_t() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_size_t() {
-// CPP-DEFAULT: size_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: void emitc_switch_size_t() {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -151,8 +141,7 @@ func.func @emitc_switch_ssize_t() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -162,8 +151,7 @@ func.func @emitc_switch_ssize_t() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -189,20 +177,18 @@ func.func @emitc_switch_size_t() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_index() {
-// CPP-DEFAULT: size_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: void emitc_switch_index() {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -214,8 +200,7 @@ func.func @emitc_switch_size_t() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -225,8 +210,7 @@ func.func @emitc_switch_size_t() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -252,20 +236,18 @@ func.func @emitc_switch_index() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_opaque() {
-// CPP-DEFAULT: size_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: void emitc_switch_opaque() {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -277,8 +259,7 @@ func.func @emitc_switch_index() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -288,8 +269,7 @@ func.func @emitc_switch_index() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -316,20 +296,18 @@ func.func @emitc_switch_opaque() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_i1() {
-// CPP-DEFAULT: bool v1 = true;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: void emitc_switch_i1() {
+// CPP-DEFAULT: switch (true) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -341,8 +319,7 @@ func.func @emitc_switch_opaque() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = true;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (true) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -352,8 +329,7 @@ func.func @emitc_switch_opaque() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -379,20 +355,18 @@ func.func @emitc_switch_i1() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_i8() {
-// CPP-DEFAULT: int8_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: void emitc_switch_i8() {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -404,8 +378,7 @@ func.func @emitc_switch_i1() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -415,8 +388,7 @@ func.func @emitc_switch_i1() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
-// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func2(4.200000000e+01f);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: }
@@ -442,20 +414,18 @@ func.func @emitc_switch_i8() {
return
}
-// CPP-DEFAULT-LABEL: void emitc_switch_ui8() {
-// CPP-DEFAULT: uint8_t v1 = 1;
-// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: void emitc_switch_ui8() {
+// CPP-DEFAULT: switch (1) {
// CPP-DEFAULT: case 2: {
-// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: int32_t v1 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: case 5: {
-// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: int32_t v2 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
-// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func2(4.200000000e+01f);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: }
@@ -467,8 +437,7 @@ func.func @emitc_switch_i8() {
// CPP-DECLTOP: float v2;
// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: v1 = 1;
-// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: switch (1) {
// CPP-DECLTOP: case 2: {
// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
@@ -478,8 +447,7 @@ func.func @emitc_switch_i8() {
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// ...
[truncated]
|
// CPP-DEFAULT: int32_t [[V0:[^ ]*]] = 0; | ||
// CPP-DEFAULT: float [[V1:[^ ]*]] = 1.000000000e+00f; | ||
// CPP-DEFAULT: return std::make_tuple([[V0]], [[V1]]); | ||
// CPP-DEFAULT: return std::make_tuple(0, 1.000000000e+00f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we emit casts to ensure that the integer literal has the right type? Otherwise this will cause template type inference to change. E.g. If V0
was int64_t here, how would the C++ code look? Maybe you can add a test case to show that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks to point this, I think maybe we can use literal suffix? By example, emit constant of int64_t to 0ll
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These suffixes map to the C types (Like Long long int) and the width of these are architecture dependent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, same integer width doesn't mean the same type, so when the user of constant is a call or std::tuple and std::tie, we need emit a explicit type cast around it.
Can this be moved from the Translation layer to a conversion pass? We have the Expression op which gets inlined under the right conditions. On top of that there ist already the FormExpressions pass, that does something like this. Maybe that can be reused/extended to have more control on which ops get turned into expressions. This would also have the advantage to make this feature opt in and not immediately break downstream Users. |
I agree here. If a pass can be used for this, I would strongly prefer this over adding it to the translation which we try to keep as dump as possible. |
+1. |
A constant op, such as |
One could argue that the emitc.constant shouldn't have the ConstantLike trait as it's emitted as local variables and thus has side effects. What's your opinion on this @marbre @aniragil @mgehre-amd? That would also be disruptive downstream though as constants wouldn't be deduplicated anymore. |
Right, though being sort of a "prepare for translation" transformation,
IINM |
Isn't |
I'm open to further discussions, but if it's pure then hoisting on the MLIR side is not wrong. I've thought about side effects in the past and I don't know if we want to simply mark the ops as pure as you might target overloaded C++ classes that do whatever. But especially on the call_opaque op I want to be able to mark an instance as pure with an attribute for example and then override getMemoryEffects accordingly. |
Wouldn't the constant op be able to check for that with the new interface proposed here #142771 ? We can check if the type is scalar and then e.g. say that it doesn't have side effects. |
That could be indeed an interesting solution but I haven't looked to close to the new interface and don't know if it allows to do so. |
Sorry, maybe I'm missing something: IsolatedFromAbove indeed prevents using any value defined outside the op, so the CExpressions in |
I think not only for constantOp but also other ops, we should mark it have no side effect only for builtin types. Because the op with opaque type may use overloaded operator that may access memory or have other side effect. |
The other op I think is |
Yes, they have check but most just mark it as no sideeffect. By example, all binary operator such as add is set with no side effect, but in C++, we may have an overloaded operator add which may access memory. So I think any op with opaque type should be treated as sideeffect. |
I agree, but for the PR bringing interface in, the reason was to make the current logic more manageable, but preserve the present behavior, since refactoring and behavior changes are separate matters, but interface was needed to make further more granular adjustments. |
This pr makes one used constant inlined during translation to cpp. Trying to make the generated cpp code more readable.