In D65186 and related patches, MustBeExecutedContextExplorer is introduced. This enables us to traverse instructions guaranteed to execute from function entry. If we can know the argument is used as dereferenceable or nonnull in these instructions, we can mark dereferenceable or nonnull in the argument definition:
- Memory instruction (similar to D64258)
Trace memory instruction pointer operand. Currently, only inbounds GEPs are traced.
define i64* @f(i64* %a) { entry: %add.ptr = getelementptr inbounds i64, i64* %a, i64 1 ; (because of inbounds GEP we can know that %a is at least dereferenceable(16)) store i64 1, i64* %add.ptr, align 8 ret i64* %add.ptr ; dereferenceable 8 (because above instruction stores into it) }
- Propagation from callsite (similar to D27855)
If deref or nonnull are known in call site parameter attributes we can also say that argument also that attribute.
declare void @use3(i8* %x, i8* %y, i8* %z); declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z); define void @parent1(i8* %a, i8* %b, i8* %c) { call void @use3nonnull(i8* %b, i8* %c, i8* %a) ; Above instruction is always executed so we can say that@parent1(i8* nonnnull %a, i8* nonnull %b, i8* nonnull %c) call void @use3(i8* %c, i8* %a, i8* %b) ret void }
Could we call it StateType, make the std::function a function_ref, and PP a reference please.
Also, I think it makes sense to have an early exit. Maybe make the predicate a function_ref<bool(const Instruction &, State &)> which updates the state in place if necessary and returns true as long as it wants to continue exploring.