Skip to content

Commit cb2a094

Browse files
committed
[mlir][evm] Lower bitwise, shift, 'exp', and 'mul' builtins
1 parent f2f12b8 commit cb2a094

File tree

8 files changed

+310
-35
lines changed

8 files changed

+310
-35
lines changed

libsolidity/codegen/mlir/Target/EVM/YulToStandard.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ struct Keccak256OpLowering : public OpRewritePattern<yul::Keccak256Op> {
5858
}
5959
};
6060

61+
struct ExpOpLowering : public OpRewritePattern<yul::ExpOp> {
62+
using OpRewritePattern<yul::ExpOp>::OpRewritePattern;
63+
64+
LogicalResult matchAndRewrite(yul::ExpOp op,
65+
PatternRewriter &r) const override {
66+
evm::Builder evmB(r, op.getLoc());
67+
68+
r.replaceOpWithNewOp<LLVM::IntrCallOp>(
69+
op, llvm::Intrinsic::evm_exp,
70+
/*resTy=*/r.getIntegerType(256),
71+
/*ins=*/ValueRange{op.getBase(), op.getExp()}, "evm.exp");
72+
73+
return success();
74+
}
75+
};
76+
6177
struct LogOpLowering : public OpRewritePattern<yul::LogOp> {
6278
using OpRewritePattern<yul::LogOp>::OpRewritePattern;
6379

@@ -725,6 +741,7 @@ void evm::populateYulPats(RewritePatternSet &pats) {
725741
// clang-format off
726742
UpdFreePtrOpLowering,
727743
Keccak256OpLowering,
744+
ExpOpLowering,
728745
LogOpLowering,
729746
AddressOpLowering,
730747
CallerOpLowering,

libsolidity/codegen/mlir/Yul/YulOps.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ def Yul_Keccak256Op : Yul_Op<"keccak256"> {
304304
let assemblyFormat = "$addr `,` $size attr-dict";
305305
}
306306

307+
def Yul_ExpOp : Yul_Op<"exp", [Pure]> {
308+
let summary = "Represents the `exp` call in yul";
309+
let arguments = (ins I256:$base, I256:$exp);
310+
let results = (outs I256:$out);
311+
let assemblyFormat = "$base `,` $exp attr-dict";
312+
}
313+
307314
def Yul_LogOp : Yul_Op<"log"> {
308315
let summary = "Represents the `log*` calls in yul";
309316
let arguments = (ins I256:$addr, I256:$size, Variadic<I256>:$topics);

libsolidity/codegen/mlir/YulToMLIR.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,13 @@ void YulToMLIRPass::populateBuiltinGenMap() {
280280
using namespace mlir::yul;
281281
defSimpleBuiltinGen<arith::AddIOp>("add");
282282
defSimpleBuiltinGen<arith::SubIOp>("sub");
283+
defSimpleBuiltinGen<arith::MulIOp>("mul");
284+
defSimpleBuiltinGen<arith::AndIOp>("and");
285+
defSimpleBuiltinGen<arith::OrIOp>("or");
286+
defSimpleBuiltinGen<arith::XOrIOp>("xor");
283287
defSimpleBuiltinGen<arith::ShRUIOp, /*reverseArgs=*/true>("shr");
288+
defSimpleBuiltinGen<arith::ShLIOp, /*reverseArgs=*/true>("shl");
289+
defSimpleBuiltinGen<arith::ShRSIOp, /*reverseArgs=*/true>("sar");
284290
defCmpBuiltinGen<arith::CmpIPredicate::ult>("lt");
285291
defCmpBuiltinGen<arith::CmpIPredicate::slt>("slt");
286292
defCmpBuiltinGen<arith::CmpIPredicate::ugt>("gt");
@@ -330,6 +336,7 @@ void YulToMLIRPass::populateBuiltinGenMap() {
330336
defSimpleBuiltinGenNoRet<RevertOp>("revert");
331337
defSimpleBuiltinGenNoRet<StopOp>("stop");
332338
defSimpleBuiltinGen<Keccak256Op>("keccak256");
339+
defSimpleBuiltinGen<ExpOp>("exp");
333340
defSimpleBuiltinGen<CallValOp>("callvalue");
334341
defSimpleBuiltinGen<AddressOp>("address");
335342
defSimpleBuiltinGen<CallerOp>("caller");
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-std-mlir --mlir-target=evm --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
mstore(0, exp(mload(0), mload(32)))
6+
}
7+
}
8+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
9+
// CHECK: #Prague = #sol<EvmVersion Prague>
10+
// CHECK-NEXT: module @Test attributes {sol.evm_version = #Prague} {
11+
// CHECK-NEXT: func.func @__entry() attributes {llvm.linkage = #llvm.linkage<external>, passthrough = ["nofree", "null_pointer_is_valid"]} {
12+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc)
13+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc)
14+
// CHECK-NEXT: %0 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc1)
15+
// CHECK-NEXT: %1 = llvm.load %0 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc1)
16+
// CHECK-NEXT: %2 = llvm.inttoptr %c32_i256 : i256 to !llvm.ptr<1> loc(#loc2)
17+
// CHECK-NEXT: %3 = llvm.load %2 {alignment = 1 : i64} : !llvm.ptr<1> -> i256 loc(#loc2)
18+
// CHECK-NEXT: %4 = "llvm.intrcall"(%1, %3) <{id = 3708 : i32, name = "evm.exp"}> : (i256, i256) -> i256 loc(#loc3)
19+
// CHECK-NEXT: %5 = llvm.inttoptr %c0_i256 : i256 to !llvm.ptr<1> loc(#loc4)
20+
// CHECK-NEXT: llvm.store %4, %5 {alignment = 1 : i64} : i256, !llvm.ptr<1> loc(#loc4)
21+
// CHECK-NEXT: llvm.unreachable loc(#loc)
22+
// CHECK-NEXT: } loc(#loc)
23+
// CHECK-NEXT: } loc(#loc)
24+
// CHECK-NEXT: #loc = loc(unknown)
25+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:18)
26+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:28)
27+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:14)
28+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:4)
29+
// CHECK-EMPTY:

test/lit/mlirCodegen/yul/arith.yul

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
object "Test" {
44
code {
5-
let a := add(0, 1)
6-
let b := sub(0, 1)
7-
let c := shr(0, 1)
5+
let a := mload(0)
6+
let b := mload(32)
7+
mstore(64, add(a, b))
8+
mstore(96, sub(a, b))
9+
mstore(128, mul(a, b))
810
}
911
}
1012

@@ -13,39 +15,54 @@ object "Test" {
1315
// CHECK-NEXT: module attributes {sol.evm_version = #Prague} {
1416
// CHECK-NEXT: yul.object @Test {
1517
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc1)
16-
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc2)
17-
// CHECK-NEXT: %0 = arith.addi %c0_i256, %c1_i256 : i256 loc(#loc3)
18-
// CHECK-NEXT: %c1_i256_0 = arith.constant 1 : i256 loc(#loc4)
19-
// CHECK-NEXT: %1 = llvm.alloca %c1_i256_0 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc5)
20-
// CHECK-NEXT: llvm.store %0, %1 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc4)
21-
// CHECK-NEXT: %c0_i256_1 = arith.constant 0 : i256 loc(#loc6)
22-
// CHECK-NEXT: %c1_i256_2 = arith.constant 1 : i256 loc(#loc7)
23-
// CHECK-NEXT: %2 = arith.subi %c0_i256_1, %c1_i256_2 : i256 loc(#loc8)
24-
// CHECK-NEXT: %c1_i256_3 = arith.constant 1 : i256 loc(#loc9)
25-
// CHECK-NEXT: %3 = llvm.alloca %c1_i256_3 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc10)
26-
// CHECK-NEXT: llvm.store %2, %3 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc9)
27-
// CHECK-NEXT: %c1_i256_4 = arith.constant 1 : i256 loc(#loc11)
28-
// CHECK-NEXT: %c0_i256_5 = arith.constant 0 : i256 loc(#loc12)
29-
// CHECK-NEXT: %4 = arith.shrui %c1_i256_4, %c0_i256_5 : i256 loc(#loc13)
30-
// CHECK-NEXT: %c1_i256_6 = arith.constant 1 : i256 loc(#loc14)
31-
// CHECK-NEXT: %5 = llvm.alloca %c1_i256_6 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc15)
32-
// CHECK-NEXT: llvm.store %4, %5 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc14)
18+
// CHECK-NEXT: %0 = yul.mload %c0_i256 loc(#loc2)
19+
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc3)
20+
// CHECK-NEXT: %1 = llvm.alloca %c1_i256 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc4)
21+
// CHECK-NEXT: llvm.store %0, %1 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc3)
22+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc5)
23+
// CHECK-NEXT: %2 = yul.mload %c32_i256 loc(#loc6)
24+
// CHECK-NEXT: %c1_i256_0 = arith.constant 1 : i256 loc(#loc7)
25+
// CHECK-NEXT: %3 = llvm.alloca %c1_i256_0 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc8)
26+
// CHECK-NEXT: llvm.store %2, %3 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc7)
27+
// CHECK-NEXT: %c64_i256 = arith.constant 64 : i256 loc(#loc9)
28+
// CHECK-NEXT: %4 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc10)
29+
// CHECK-NEXT: %5 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc11)
30+
// CHECK-NEXT: %6 = arith.addi %4, %5 : i256 loc(#loc12)
31+
// CHECK-NEXT: yul.mstore %c64_i256, %6 loc(#loc13)
32+
// CHECK-NEXT: %c96_i256 = arith.constant 96 : i256 loc(#loc14)
33+
// CHECK-NEXT: %7 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc15)
34+
// CHECK-NEXT: %8 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc16)
35+
// CHECK-NEXT: %9 = arith.subi %7, %8 : i256 loc(#loc17)
36+
// CHECK-NEXT: yul.mstore %c96_i256, %9 loc(#loc18)
37+
// CHECK-NEXT: %c128_i256 = arith.constant 128 : i256 loc(#loc19)
38+
// CHECK-NEXT: %10 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc20)
39+
// CHECK-NEXT: %11 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc21)
40+
// CHECK-NEXT: %12 = arith.muli %10, %11 : i256 loc(#loc22)
41+
// CHECK-NEXT: yul.mstore %c128_i256, %12 loc(#loc23)
3342
// CHECK-NEXT: } loc(#loc)
3443
// CHECK-NEXT: } loc(#loc)
3544
// CHECK-NEXT: #loc = loc(unknown)
36-
// CHECK-NEXT: #loc1 = loc({{.*}}:4:17)
37-
// CHECK-NEXT: #loc2 = loc({{.*}}:4:20)
38-
// CHECK-NEXT: #loc3 = loc({{.*}}:4:13)
39-
// CHECK-NEXT: #loc4 = loc({{.*}}:4:4)
40-
// CHECK-NEXT: #loc5 = loc({{.*}}:4:8)
41-
// CHECK-NEXT: #loc6 = loc({{.*}}:5:17)
42-
// CHECK-NEXT: #loc7 = loc({{.*}}:5:20)
43-
// CHECK-NEXT: #loc8 = loc({{.*}}:5:13)
44-
// CHECK-NEXT: #loc9 = loc({{.*}}:5:4)
45-
// CHECK-NEXT: #loc10 = loc({{.*}}:5:8)
46-
// CHECK-NEXT: #loc11 = loc({{.*}}:6:20)
47-
// CHECK-NEXT: #loc12 = loc({{.*}}:6:17)
48-
// CHECK-NEXT: #loc13 = loc({{.*}}:6:13)
49-
// CHECK-NEXT: #loc14 = loc({{.*}}:6:4)
50-
// CHECK-NEXT: #loc15 = loc({{.*}}:6:8)
45+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:19)
46+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:13)
47+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:4)
48+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:8)
49+
// CHECK-NEXT: #loc5 = loc({{.*}}:5:19)
50+
// CHECK-NEXT: #loc6 = loc({{.*}}:5:13)
51+
// CHECK-NEXT: #loc7 = loc({{.*}}:5:4)
52+
// CHECK-NEXT: #loc8 = loc({{.*}}:5:8)
53+
// CHECK-NEXT: #loc9 = loc({{.*}}:6:11)
54+
// CHECK-NEXT: #loc10 = loc({{.*}}:6:19)
55+
// CHECK-NEXT: #loc11 = loc({{.*}}:6:22)
56+
// CHECK-NEXT: #loc12 = loc({{.*}}:6:15)
57+
// CHECK-NEXT: #loc13 = loc({{.*}}:6:4)
58+
// CHECK-NEXT: #loc14 = loc({{.*}}:7:11)
59+
// CHECK-NEXT: #loc15 = loc({{.*}}:7:19)
60+
// CHECK-NEXT: #loc16 = loc({{.*}}:7:22)
61+
// CHECK-NEXT: #loc17 = loc({{.*}}:7:15)
62+
// CHECK-NEXT: #loc18 = loc({{.*}}:7:4)
63+
// CHECK-NEXT: #loc19 = loc({{.*}}:8:11)
64+
// CHECK-NEXT: #loc20 = loc({{.*}}:8:20)
65+
// CHECK-NEXT: #loc21 = loc({{.*}}:8:23)
66+
// CHECK-NEXT: #loc22 = loc({{.*}}:8:16)
67+
// CHECK-NEXT: #loc23 = loc({{.*}}:8:4)
5168
// CHECK-EMPTY:
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-init --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
let a := mload(0)
6+
let b := mload(32)
7+
mstore(64, and(a, b))
8+
mstore(96, or(a, b))
9+
mstore(128, xor(a, b))
10+
}
11+
}
12+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
13+
// CHECK: #Prague = #sol<EvmVersion Prague>
14+
// CHECK-NEXT: module attributes {sol.evm_version = #Prague} {
15+
// CHECK-NEXT: yul.object @Test {
16+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc1)
17+
// CHECK-NEXT: %0 = yul.mload %c0_i256 loc(#loc2)
18+
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc3)
19+
// CHECK-NEXT: %1 = llvm.alloca %c1_i256 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc4)
20+
// CHECK-NEXT: llvm.store %0, %1 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc3)
21+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc5)
22+
// CHECK-NEXT: %2 = yul.mload %c32_i256 loc(#loc6)
23+
// CHECK-NEXT: %c1_i256_0 = arith.constant 1 : i256 loc(#loc7)
24+
// CHECK-NEXT: %3 = llvm.alloca %c1_i256_0 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc8)
25+
// CHECK-NEXT: llvm.store %2, %3 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc7)
26+
// CHECK-NEXT: %c64_i256 = arith.constant 64 : i256 loc(#loc9)
27+
// CHECK-NEXT: %4 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc10)
28+
// CHECK-NEXT: %5 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc11)
29+
// CHECK-NEXT: %6 = arith.andi %4, %5 : i256 loc(#loc12)
30+
// CHECK-NEXT: yul.mstore %c64_i256, %6 loc(#loc13)
31+
// CHECK-NEXT: %c96_i256 = arith.constant 96 : i256 loc(#loc14)
32+
// CHECK-NEXT: %7 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc15)
33+
// CHECK-NEXT: %8 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc16)
34+
// CHECK-NEXT: %9 = arith.ori %7, %8 : i256 loc(#loc17)
35+
// CHECK-NEXT: yul.mstore %c96_i256, %9 loc(#loc18)
36+
// CHECK-NEXT: %c128_i256 = arith.constant 128 : i256 loc(#loc19)
37+
// CHECK-NEXT: %10 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc20)
38+
// CHECK-NEXT: %11 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc21)
39+
// CHECK-NEXT: %12 = arith.xori %10, %11 : i256 loc(#loc22)
40+
// CHECK-NEXT: yul.mstore %c128_i256, %12 loc(#loc23)
41+
// CHECK-NEXT: } loc(#loc)
42+
// CHECK-NEXT: } loc(#loc)
43+
// CHECK-NEXT: #loc = loc(unknown)
44+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:19)
45+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:13)
46+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:4)
47+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:8)
48+
// CHECK-NEXT: #loc5 = loc({{.*}}:5:19)
49+
// CHECK-NEXT: #loc6 = loc({{.*}}:5:13)
50+
// CHECK-NEXT: #loc7 = loc({{.*}}:5:4)
51+
// CHECK-NEXT: #loc8 = loc({{.*}}:5:8)
52+
// CHECK-NEXT: #loc9 = loc({{.*}}:6:11)
53+
// CHECK-NEXT: #loc10 = loc({{.*}}:6:19)
54+
// CHECK-NEXT: #loc11 = loc({{.*}}:6:22)
55+
// CHECK-NEXT: #loc12 = loc({{.*}}:6:15)
56+
// CHECK-NEXT: #loc13 = loc({{.*}}:6:4)
57+
// CHECK-NEXT: #loc14 = loc({{.*}}:7:11)
58+
// CHECK-NEXT: #loc15 = loc({{.*}}:7:18)
59+
// CHECK-NEXT: #loc16 = loc({{.*}}:7:21)
60+
// CHECK-NEXT: #loc17 = loc({{.*}}:7:15)
61+
// CHECK-NEXT: #loc18 = loc({{.*}}:7:4)
62+
// CHECK-NEXT: #loc19 = loc({{.*}}:8:11)
63+
// CHECK-NEXT: #loc20 = loc({{.*}}:8:20)
64+
// CHECK-NEXT: #loc21 = loc({{.*}}:8:23)
65+
// CHECK-NEXT: #loc22 = loc({{.*}}:8:16)
66+
// CHECK-NEXT: #loc23 = loc({{.*}}:8:4)
67+
// CHECK-EMPTY:

test/lit/mlirCodegen/yul/exp.yul

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-init --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
let a := mload(0)
6+
let b := mload(32)
7+
mstore(0, exp(a, b))
8+
return(0, 32)
9+
}
10+
object "Test_deployed" {
11+
code {}
12+
}
13+
}
14+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
15+
// CHECK: #Prague = #sol<EvmVersion Prague>
16+
// CHECK-NEXT: module attributes {sol.evm_version = #Prague} {
17+
// CHECK-NEXT: yul.object @Test {
18+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc1)
19+
// CHECK-NEXT: %0 = yul.mload %c0_i256 loc(#loc2)
20+
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc3)
21+
// CHECK-NEXT: %1 = llvm.alloca %c1_i256 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc4)
22+
// CHECK-NEXT: llvm.store %0, %1 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc3)
23+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc5)
24+
// CHECK-NEXT: %2 = yul.mload %c32_i256 loc(#loc6)
25+
// CHECK-NEXT: %c1_i256_0 = arith.constant 1 : i256 loc(#loc7)
26+
// CHECK-NEXT: %3 = llvm.alloca %c1_i256_0 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc8)
27+
// CHECK-NEXT: llvm.store %2, %3 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc7)
28+
// CHECK-NEXT: %c0_i256_1 = arith.constant 0 : i256 loc(#loc9)
29+
// CHECK-NEXT: %4 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc10)
30+
// CHECK-NEXT: %5 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc11)
31+
// CHECK-NEXT: %6 = yul.exp %4, %5 loc(#loc12)
32+
// CHECK-NEXT: yul.mstore %c0_i256_1, %6 loc(#loc13)
33+
// CHECK-NEXT: %c0_i256_2 = arith.constant 0 : i256 loc(#loc14)
34+
// CHECK-NEXT: %c32_i256_3 = arith.constant 32 : i256 loc(#loc15)
35+
// CHECK-NEXT: yul.return %c0_i256_2, %c32_i256_3 loc(#loc16)
36+
// CHECK-NEXT: yul.object @Test_deployed {
37+
// CHECK-NEXT: } loc(#loc)
38+
// CHECK-NEXT: } loc(#loc)
39+
// CHECK-NEXT: } loc(#loc)
40+
// CHECK-NEXT: #loc = loc(unknown)
41+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:19)
42+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:13)
43+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:4)
44+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:8)
45+
// CHECK-NEXT: #loc5 = loc({{.*}}:5:19)
46+
// CHECK-NEXT: #loc6 = loc({{.*}}:5:13)
47+
// CHECK-NEXT: #loc7 = loc({{.*}}:5:4)
48+
// CHECK-NEXT: #loc8 = loc({{.*}}:5:8)
49+
// CHECK-NEXT: #loc9 = loc({{.*}}:6:11)
50+
// CHECK-NEXT: #loc10 = loc({{.*}}:6:18)
51+
// CHECK-NEXT: #loc11 = loc({{.*}}:6:21)
52+
// CHECK-NEXT: #loc12 = loc({{.*}}:6:14)
53+
// CHECK-NEXT: #loc13 = loc({{.*}}:6:4)
54+
// CHECK-NEXT: #loc14 = loc({{.*}}:7:11)
55+
// CHECK-NEXT: #loc15 = loc({{.*}}:7:14)
56+
// CHECK-NEXT: #loc16 = loc({{.*}}:7:4)
57+
// CHECK-EMPTY:
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: solc --strict-assembly --mlir-action=print-init --mmlir --mlir-print-debuginfo %s | FileCheck %s
2+
3+
object "Test" {
4+
code {
5+
let a := mload(0)
6+
let b := mload(32)
7+
mstore(64, shl(a, b))
8+
mstore(96, shr(a, b))
9+
mstore(128, sar(a, b))
10+
return(64, 96)
11+
}
12+
}
13+
// NOTE: Assertions have been autogenerated by test/updFileCheckTest.py
14+
// CHECK: #Prague = #sol<EvmVersion Prague>
15+
// CHECK-NEXT: module attributes {sol.evm_version = #Prague} {
16+
// CHECK-NEXT: yul.object @Test {
17+
// CHECK-NEXT: %c0_i256 = arith.constant 0 : i256 loc(#loc1)
18+
// CHECK-NEXT: %0 = yul.mload %c0_i256 loc(#loc2)
19+
// CHECK-NEXT: %c1_i256 = arith.constant 1 : i256 loc(#loc3)
20+
// CHECK-NEXT: %1 = llvm.alloca %c1_i256 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc4)
21+
// CHECK-NEXT: llvm.store %0, %1 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc3)
22+
// CHECK-NEXT: %c32_i256 = arith.constant 32 : i256 loc(#loc5)
23+
// CHECK-NEXT: %2 = yul.mload %c32_i256 loc(#loc6)
24+
// CHECK-NEXT: %c1_i256_0 = arith.constant 1 : i256 loc(#loc7)
25+
// CHECK-NEXT: %3 = llvm.alloca %c1_i256_0 x i256 {alignment = 32 : i64} : (i256) -> !llvm.ptr loc(#loc8)
26+
// CHECK-NEXT: llvm.store %2, %3 {alignment = 32 : i64} : i256, !llvm.ptr loc(#loc7)
27+
// CHECK-NEXT: %c64_i256 = arith.constant 64 : i256 loc(#loc9)
28+
// CHECK-NEXT: %4 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc10)
29+
// CHECK-NEXT: %5 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc11)
30+
// CHECK-NEXT: %6 = arith.shli %4, %5 : i256 loc(#loc12)
31+
// CHECK-NEXT: yul.mstore %c64_i256, %6 loc(#loc13)
32+
// CHECK-NEXT: %c96_i256 = arith.constant 96 : i256 loc(#loc14)
33+
// CHECK-NEXT: %7 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc15)
34+
// CHECK-NEXT: %8 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc16)
35+
// CHECK-NEXT: %9 = arith.shrui %7, %8 : i256 loc(#loc17)
36+
// CHECK-NEXT: yul.mstore %c96_i256, %9 loc(#loc18)
37+
// CHECK-NEXT: %c128_i256 = arith.constant 128 : i256 loc(#loc19)
38+
// CHECK-NEXT: %10 = llvm.load %3 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc20)
39+
// CHECK-NEXT: %11 = llvm.load %1 {alignment = 32 : i64} : !llvm.ptr -> i256 loc(#loc21)
40+
// CHECK-NEXT: %12 = arith.shrsi %10, %11 : i256 loc(#loc22)
41+
// CHECK-NEXT: yul.mstore %c128_i256, %12 loc(#loc23)
42+
// CHECK-NEXT: %c64_i256_1 = arith.constant 64 : i256 loc(#loc24)
43+
// CHECK-NEXT: %c96_i256_2 = arith.constant 96 : i256 loc(#loc25)
44+
// CHECK-NEXT: yul.return %c64_i256_1, %c96_i256_2 loc(#loc26)
45+
// CHECK-NEXT: } loc(#loc)
46+
// CHECK-NEXT: } loc(#loc)
47+
// CHECK-NEXT: #loc = loc(unknown)
48+
// CHECK-NEXT: #loc1 = loc({{.*}}:4:19)
49+
// CHECK-NEXT: #loc2 = loc({{.*}}:4:13)
50+
// CHECK-NEXT: #loc3 = loc({{.*}}:4:4)
51+
// CHECK-NEXT: #loc4 = loc({{.*}}:4:8)
52+
// CHECK-NEXT: #loc5 = loc({{.*}}:5:19)
53+
// CHECK-NEXT: #loc6 = loc({{.*}}:5:13)
54+
// CHECK-NEXT: #loc7 = loc({{.*}}:5:4)
55+
// CHECK-NEXT: #loc8 = loc({{.*}}:5:8)
56+
// CHECK-NEXT: #loc9 = loc({{.*}}:6:11)
57+
// CHECK-NEXT: #loc10 = loc({{.*}}:6:22)
58+
// CHECK-NEXT: #loc11 = loc({{.*}}:6:19)
59+
// CHECK-NEXT: #loc12 = loc({{.*}}:6:15)
60+
// CHECK-NEXT: #loc13 = loc({{.*}}:6:4)
61+
// CHECK-NEXT: #loc14 = loc({{.*}}:7:11)
62+
// CHECK-NEXT: #loc15 = loc({{.*}}:7:22)
63+
// CHECK-NEXT: #loc16 = loc({{.*}}:7:19)
64+
// CHECK-NEXT: #loc17 = loc({{.*}}:7:15)
65+
// CHECK-NEXT: #loc18 = loc({{.*}}:7:4)
66+
// CHECK-NEXT: #loc19 = loc({{.*}}:8:11)
67+
// CHECK-NEXT: #loc20 = loc({{.*}}:8:23)
68+
// CHECK-NEXT: #loc21 = loc({{.*}}:8:20)
69+
// CHECK-NEXT: #loc22 = loc({{.*}}:8:16)
70+
// CHECK-NEXT: #loc23 = loc({{.*}}:8:4)
71+
// CHECK-NEXT: #loc24 = loc({{.*}}:9:11)
72+
// CHECK-NEXT: #loc25 = loc({{.*}}:9:15)
73+
// CHECK-NEXT: #loc26 = loc({{.*}}:9:4)
74+
// CHECK-EMPTY:

0 commit comments

Comments
 (0)