Skip to content

Commit 98b010d

Browse files
committed
[EVM] Refine the memory effects of intrinsics for greater accuracy
This involved modifying both the TableGen descriptions and the EVM AliasAnalysis.
1 parent a9e468e commit 98b010d

File tree

6 files changed

+280
-156
lines changed

6 files changed

+280
-156
lines changed

llvm/include/llvm/IR/IntrinsicsEVM.td

Lines changed: 145 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ def int_evm_exp
8888
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;
8989

9090
def int_evm_sha3
91-
: Intrinsic<[llvm_i256_ty],
92-
[LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
93-
[IntrReadMem,IntrArgMemOnly, IntrWillReturn]>;
91+
: Intrinsic<[llvm_i256_ty], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
92+
[IntrReadMem, IntrArgMemOnly, IntrNoCallback,
93+
NoCapture<ArgIndex<0>>, IntrWillReturn]>;
9494

9595
def int_evm_signextend
9696
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;
@@ -100,8 +100,10 @@ def int_evm_byte
100100
[IntrNoMem, IntrWillReturn]>;
101101

102102
// Memory operations.
103-
def int_evm_mstore8 : Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
104-
[IntrWriteMem, IntrArgMemOnly]>;
103+
def int_evm_mstore8
104+
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
105+
[IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<0>>,
106+
IntrNoCallback, IntrWillReturn]>;
105107

106108
// Special getters that must not be relocated.
107109
def int_evm_msize : Intrinsic<[llvm_i256_ty], [], [IntrWillReturn]>;
@@ -119,146 +121,182 @@ def int_evm_origin : Intrinsic<[llvm_i256_ty], [],
119121
def int_evm_caller : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;
120122

121123
def int_evm_balance : Intrinsic<[llvm_i256_ty], [llvm_i256_ty],
122-
[IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
124+
[IntrReadMem, IntrInaccessibleMemOnly,
125+
IntrNoCallback, IntrWillReturn]>;
123126

124127
def int_evm_callvalue : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;
125128

126129
def int_evm_calldatasize : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;
127130

128131
def int_evm_calldataload
129-
: Intrinsic<[llvm_i256_ty], [LLVMQualPointerType<AS.CALL_DATA>],
130-
[IntrReadMem, IntrArgMemOnly]>;
132+
: Intrinsic<[llvm_i256_ty], [LLVMQualPointerType<AS.CALL_DATA>],
133+
[IntrReadMem, IntrArgMemOnly, IntrNoCallback, IntrWillReturn]>;
131134

132-
def int_evm_codesize : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;
135+
def int_evm_codesize : Intrinsic<[llvm_i256_ty], [],
136+
[IntrNoMem, IntrNoCallback, IntrWillReturn]>;
133137

134-
def int_evm_gasprice : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
135-
IntrWillReturn]>;
138+
def int_evm_gasprice : Intrinsic<[llvm_i256_ty], [],
139+
[IntrReadMem, IntrInaccessibleMemOnly,
140+
IntrNoCallback, IntrWillReturn]>;
136141

137-
def int_evm_extcodesize
138-
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
142+
def int_evm_extcodesize : Intrinsic<[llvm_i256_ty], [llvm_i256_ty],
143+
[IntrReadMem, IntrInaccessibleMemOnly,
144+
IntrNoCallback, IntrWillReturn]>;
139145

140-
// This should have 'read of inaccessible' memory along with read/write memory accessed through
141-
// its pointer-typed arguments. Since we can't express that precisely here, we represent
142-
// it as read/write access to arbitrary memory.
143146
def int_evm_extcodecopy
144-
: Intrinsic<[], [llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
145-
LLVMQualPointerType<AS.CODE>, llvm_i256_ty], [IntrWillReturn]>;
147+
: Intrinsic<[],
148+
[llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
149+
LLVMQualPointerType<AS.CODE>, llvm_i256_ty],
150+
[IntrInaccessibleMemOrArgMemOnly, WriteOnly<ArgIndex<1>>,
151+
ReadOnly<ArgIndex<2>>, NoCapture<ArgIndex<1>>,
152+
NoCapture<ArgIndex<2>>, IntrNoCallback, IntrWillReturn]>;
146153

147-
def int_evm_returndatasize
148-
: Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
154+
def int_evm_returndatasize : Intrinsic<[llvm_i256_ty], [],
155+
[IntrReadMem, IntrInaccessibleMemOnly,
156+
IntrNoCallback, IntrWillReturn]>;
149157

150-
def int_evm_extcodehash
151-
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
158+
def int_evm_extcodehash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty],
159+
[IntrReadMem, IntrInaccessibleMemOnly,
160+
IntrNoCallback, IntrWillReturn]>;
152161

153162
def int_evm_blockhash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty],
154-
[IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
163+
[IntrReadMem, IntrInaccessibleMemOnly,
164+
IntrNoCallback, IntrWillReturn]>;
155165

156166
def int_evm_blobhash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty],
157-
[IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
158-
159-
def int_evm_coinbase : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
160-
IntrWillReturn]>;
161-
162-
def int_evm_timestamp : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
163-
IntrWillReturn]>;
164-
165-
def int_evm_number : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
166-
IntrWillReturn]>;
167-
168-
def int_evm_difficulty : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
169-
IntrWillReturn]>;
170-
171-
def int_evm_gaslimit : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
172-
IntrWillReturn]>;
173-
174-
def int_evm_chainid : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
175-
IntrWillReturn]>;
176-
177-
def int_evm_selfbalance
178-
: Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly, IntrWillReturn]>;
179-
180-
def int_evm_basefee : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
181-
IntrWillReturn]>;
182-
183-
def int_evm_blobbasefee : Intrinsic<[llvm_i256_ty], [], [IntrReadMem, IntrInaccessibleMemOnly,
184-
IntrWillReturn]>;
185-
186-
// Logging.
187-
// Log intrinsics should have 'read/write of inaccessible' memory along with read memory
188-
// accessed through its pointer-typed arguments. Since we can't express that precisely
189-
// here, we represent it as read/write access to arbitrary memory.
190-
// Note: Attempting to mark them with both IntrReadMem and IntrHasSideEffects won't work,
191-
// because IntrHasSideEffects does not override IntrReadMem. As a result, intrinsics will
192-
// lack the 'HasSideEffects' flag entirely, making them subject to DCE.
193-
def int_evm_log0 : Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
194-
[IntrWillReturn]>;
195-
196-
def int_evm_log1 : Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty],
197-
[IntrWillReturn]>;
198-
199-
def int_evm_log2 : Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
200-
llvm_i256_ty, llvm_i256_ty],
201-
[IntrWillReturn]>;
202-
203-
def int_evm_log3 : Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
204-
llvm_i256_ty, llvm_i256_ty, llvm_i256_ty],
205-
[IntrWillReturn]>;
206-
207-
def int_evm_log4 : Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
208-
llvm_i256_ty, llvm_i256_ty, llvm_i256_ty],
209-
[IntrWillReturn]>;
167+
[IntrReadMem, IntrInaccessibleMemOnly,
168+
IntrNoCallback, IntrWillReturn]>;
169+
170+
def int_evm_coinbase : Intrinsic<[llvm_i256_ty], [],
171+
[IntrReadMem, IntrInaccessibleMemOnly,
172+
IntrNoCallback, IntrWillReturn]>;
173+
174+
def int_evm_timestamp : Intrinsic<[llvm_i256_ty], [],
175+
[IntrReadMem, IntrInaccessibleMemOnly,
176+
IntrNoCallback, IntrWillReturn]>;
177+
178+
def int_evm_number : Intrinsic<[llvm_i256_ty], [],
179+
[IntrReadMem, IntrInaccessibleMemOnly,
180+
IntrNoCallback, IntrWillReturn]>;
181+
182+
def int_evm_difficulty : Intrinsic<[llvm_i256_ty], [],
183+
[IntrReadMem, IntrInaccessibleMemOnly,
184+
IntrNoCallback, IntrWillReturn]>;
185+
186+
def int_evm_gaslimit : Intrinsic<[llvm_i256_ty], [],
187+
[IntrReadMem, IntrInaccessibleMemOnly,
188+
IntrNoCallback, IntrWillReturn]>;
189+
190+
def int_evm_chainid : Intrinsic<[llvm_i256_ty], [],
191+
[IntrReadMem, IntrInaccessibleMemOnly,
192+
IntrNoCallback, IntrWillReturn]>;
193+
194+
def int_evm_selfbalance : Intrinsic<[llvm_i256_ty], [],
195+
[IntrReadMem, IntrInaccessibleMemOnly,
196+
IntrNoCallback, IntrWillReturn]>;
197+
198+
def int_evm_basefee : Intrinsic<[llvm_i256_ty], [],
199+
[IntrReadMem, IntrInaccessibleMemOnly,
200+
IntrNoCallback, IntrWillReturn]>;
201+
202+
def int_evm_blobbasefee : Intrinsic<[llvm_i256_ty], [],
203+
[IntrReadMem, IntrInaccessibleMemOnly,
204+
IntrNoCallback, IntrWillReturn]>;
205+
206+
// Logging
207+
def int_evm_log0
208+
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
209+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
210+
NoCapture<ArgIndex<0>>, IntrNoCallback, IntrWillReturn]>;
211+
212+
def int_evm_log1
213+
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty],
214+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
215+
NoCapture<ArgIndex<0>>, IntrNoCallback, IntrWillReturn]>;
216+
217+
def int_evm_log2
218+
: Intrinsic<[],
219+
[LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
220+
llvm_i256_ty],
221+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
222+
NoCapture<ArgIndex<0>>, IntrNoCallback, IntrWillReturn]>;
223+
224+
def int_evm_log3
225+
: Intrinsic<[],
226+
[LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
227+
llvm_i256_ty, llvm_i256_ty],
228+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
229+
NoCapture<ArgIndex<0>>, IntrNoCallback, IntrWillReturn]>;
230+
231+
def int_evm_log4
232+
: Intrinsic<[],
233+
[LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
234+
llvm_i256_ty, llvm_i256_ty, llvm_i256_ty],
235+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
236+
NoCapture<ArgIndex<0>>, IntrNoCallback, IntrWillReturn]>;
210237

211238
// System calls
212-
// The above considerations also apply to xCALL intrinsics.
213239
def int_evm_create
214-
: Intrinsic<[llvm_i256_ty],
215-
[llvm_i256_ty, LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
216-
[IntrWillReturn]>;
240+
: Intrinsic<[llvm_i256_ty],
241+
[llvm_i256_ty, LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
242+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<1>>,
243+
NoCapture<ArgIndex<1>>, IntrNoCallback, IntrWillReturn]>;
217244

218245
def int_evm_call
219-
: Intrinsic<[llvm_i256_ty],
220-
[llvm_i256_ty, llvm_i256_ty, llvm_i256_ty,
221-
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
222-
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrWillReturn]>;
246+
: Intrinsic<[llvm_i256_ty],
247+
[llvm_i256_ty, llvm_i256_ty, llvm_i256_ty,
248+
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
249+
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
250+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<3>>,
251+
WriteOnly<ArgIndex<5>>, NoCapture<ArgIndex<3>>,
252+
NoCapture<ArgIndex<5>>, IntrNoCallback, IntrWillReturn]>;
223253

224254
def int_evm_callcode
225-
: Intrinsic<[llvm_i256_ty],
226-
[llvm_i256_ty, llvm_i256_ty, llvm_i256_ty,
227-
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
228-
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrWillReturn]>;
255+
: Intrinsic<[llvm_i256_ty],
256+
[llvm_i256_ty, llvm_i256_ty, llvm_i256_ty,
257+
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
258+
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
259+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<3>>,
260+
WriteOnly<ArgIndex<5>>, NoCapture<ArgIndex<3>>,
261+
NoCapture<ArgIndex<5>>, IntrNoCallback, IntrWillReturn]>;
229262

230263
def int_evm_delegatecall
231-
: Intrinsic<[llvm_i256_ty],
232-
[llvm_i256_ty, llvm_i256_ty,
233-
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
234-
LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrWillReturn]>;
264+
: Intrinsic<[llvm_i256_ty],
265+
[llvm_i256_ty, llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
266+
llvm_i256_ty, LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
267+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<2>>,
268+
WriteOnly<ArgIndex<4>>, NoCapture<ArgIndex<2>>,
269+
NoCapture<ArgIndex<4>>, IntrNoCallback, IntrWillReturn]>;
235270

236271
def int_evm_create2
237-
: Intrinsic<[llvm_i256_ty],
238-
[llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
239-
llvm_i256_ty, llvm_i256_ty], [IntrWillReturn]>;
272+
: Intrinsic<[llvm_i256_ty],
273+
[llvm_i256_ty, LLVMQualPointerType<AS.HEAP>, llvm_i256_ty,
274+
llvm_i256_ty],
275+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<1>>,
276+
NoCapture<ArgIndex<1>>, IntrNoCallback, IntrWillReturn]>;
240277

241278
def int_evm_staticcall
242-
: Intrinsic<[llvm_i256_ty],
243-
[llvm_i256_ty, llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
244-
llvm_i256_ty, LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
245-
[IntrWillReturn]>;
246-
279+
: Intrinsic<[llvm_i256_ty],
280+
[llvm_i256_ty, llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
281+
llvm_i256_ty, LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
282+
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<2>>,
283+
WriteOnly<ArgIndex<4>>, NoCapture<ArgIndex<2>>,
284+
NoCapture<ArgIndex<4>>, IntrNoCallback, IntrWillReturn]>;
247285

248286
def int_evm_selfdestruct: Intrinsic<[], [llvm_i256_ty], []>;
249287

250288
def int_evm_stop: Intrinsic<[], [], [IntrNoReturn]>;
251289

252290
def int_evm_invalid: Intrinsic<[], [], [IntrNoReturn]>;
253291

254-
// Return with error.
255-
// These should ideally have the IntrReadMem attribute, but doing so causes DSE
256-
// to incorrectly eliminate necessary stores.
257-
def int_evm_return: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
258-
[IntrNoReturn]>;
292+
// Return with error
293+
def int_evm_return :
294+
Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
295+
[IntrReadMem, IntrArgMemOnly, ReadOnly<ArgIndex<0>>, IntrNoReturn]>;
259296

260-
def int_evm_revert: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
261-
[IntrNoReturn]>;
297+
def int_evm_revert :
298+
Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty],
299+
[IntrReadMem, IntrArgMemOnly, ReadOnly<ArgIndex<0>>, IntrNoReturn]>;
262300

263301
def int_evm_memmoveas1as1
264302
: Intrinsic<[],

llvm/lib/Analysis/AliasAnalysis.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
#include "llvm/IR/BasicBlock.h"
4141
#include "llvm/IR/Instruction.h"
4242
#include "llvm/IR/Instructions.h"
43+
// EVM local begin
44+
#include "llvm/IR/IntrinsicInst.h"
45+
#include "llvm/IR/IntrinsicsEVM.h"
46+
// EVM local end
4347
#include "llvm/IR/Type.h"
4448
#include "llvm/IR/Value.h"
4549
#include "llvm/InitializePasses.h"
@@ -123,10 +127,33 @@ AliasResult AAResults::alias(const MemoryLocation &LocA,
123127
}
124128

125129
AAQI.Depth++;
126-
for (const auto &AA : AAs) {
127-
Result = AA->alias(LocA, LocB, AAQI, CtxI);
128-
if (Result != AliasResult::MayAlias)
130+
131+
if (const auto *II = dyn_cast_or_null<IntrinsicInst>(CtxI)) {
132+
switch (II->getIntrinsicID()) {
133+
case Intrinsic::evm_return:
134+
case Intrinsic::evm_revert:
135+
case Intrinsic::evm_create:
136+
case Intrinsic::evm_create2:
137+
case Intrinsic::evm_call:
138+
case Intrinsic::evm_callcode:
139+
case Intrinsic::evm_delegatecall:
140+
case Intrinsic::evm_staticcall: {
141+
unsigned ASB = LocB.Ptr->getType()->getPointerAddressSpace();
142+
if (ASB == 5 || ASB == 6) {
143+
Result = AliasResult::MustAlias;
144+
}
145+
} break;
146+
default:
129147
break;
148+
}
149+
}
150+
151+
if (Result == AliasResult::MayAlias) {
152+
for (const auto &AA : AAs) {
153+
Result = AA->alias(LocA, LocB, AAQI, CtxI);
154+
if (Result != AliasResult::MayAlias)
155+
break;
156+
}
130157
}
131158
AAQI.Depth--;
132159

@@ -215,6 +242,28 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
215242
AAQueryInfo &AAQI) {
216243
ModRefInfo Result = ModRefInfo::ModRef;
217244

245+
if (const auto *II = dyn_cast<IntrinsicInst>(Call)) {
246+
unsigned LocAS = Loc.Ptr->getType()->getPointerAddressSpace();
247+
switch (II->getIntrinsicID()) {
248+
case Intrinsic::evm_return:
249+
case Intrinsic::evm_revert:
250+
if (LocAS == 5 || LocAS == 6)
251+
return ModRefInfo::Ref;
252+
break;
253+
case Intrinsic::evm_create:
254+
case Intrinsic::evm_create2:
255+
case Intrinsic::evm_call:
256+
case Intrinsic::evm_callcode:
257+
case Intrinsic::evm_delegatecall:
258+
case Intrinsic::evm_staticcall:
259+
if (LocAS == 5 || LocAS == 6)
260+
return ModRefInfo::ModRef;
261+
break;
262+
default:
263+
break;
264+
}
265+
}
266+
218267
for (const auto &AA : AAs) {
219268
Result &= AA->getModRefInfo(Call, Loc, AAQI);
220269

0 commit comments

Comments
 (0)