This is a draft of the directive.scope.entry/directive.scope.exit intrinsics I mentioned in the "[llvm-dev] [RFC] IR-level Region Annotations" thread[1]. Currently this patch do not have a concrete use case, it just demonstrate the general idea:
- directive.scope.entry defines a token and directive.scope.exit consumes the token defined by directive.scope.entry.
- directive.scope.entry mark the entry of the region and directive.scope.exit mark the exit of the token in the CFG
- Extra information of the region is annotated as operand bundle of the directive.scope.entry intrinsic.
For example, from:
#pragma prefetch x:1:20 y:0:10 for (i=0; i<2*N; i++) { xp[i*m + j] = -1; yp[i*n +j] = -2; }
we can generate the region annotation as:
%0 = tail call token @llvm.directive.scope.entry() [ "prefetch"(i32 *xp, i64 1, i64 20, i32 *yp, i64 0, i64 10) ] ... loop ... tail call void @llvm.directive.scope.exit(token %0)
Or
#pragma omp parallel for for (i=0; i<2*N; i++) { xp[i] =0; }
we can generate:
%0 = tail call token @llvm.directive.scope.entry() [ "omp.parallel.for"() ] ... loop ... tail call void @llvm.directive.scope.exit(token %0)
Based on these intrinsics, we can introduce wrapper classes to represent different regions:
class OmpParallelForDirective: public IntrinsicInst { public: static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::directive_scope_entry && hasOperandBundle("omp.parallel.for"); // later we can replace this by an enum } ... Instruction *getRegionEntry() const; Instruction *getRegionExit() const; } class PrefetchDirective: public IntrinsicInst { public: static inline bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::directive_scope_entry && hasOperandBundle("prefetch"); } ArrayRef<Value*> getValues() const; // return { xp, yp } in the previous example Instruction *getRegionEntry() const; Instruction *getRegionExit() const; }
[1]https://groups.google.com/d/msg/llvm-dev/uSlv-hZJm_Y/KRSWE9pgEAAJ