<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Yes, that's exactly it - I have a small amount of extra code that
      I want to run on MachineFunctions within the X86 target machine
      implementation. I've tried a couple of ways around this and the
      easiest way I've come up with is very similar to the
      PassManagerBuilder::addGlobalExtension used for IR passes. I'll
      post some code below showing the interface, in case anyone has any
      feedback before I write some tests for a patch submission.<br>
    </p>
    <p>My apologies for taking so long to reply, by the way.</p>
    <p>The basic idea is to add an enum for different extension points
      within TargetPassConfig and keep a global list of per-target
      extensions. The interface changes look like the below. The
      existing addPass function has to be made public so the client code
      can use it from the callback function that it registers.<br>
    </p>
    <blockquote> class TargetPassConfig : public ImmutablePass {<br>
      <p>+public:<br>
        +  enum CodegenExtensionPointTy {<br>
        +    CGEP_EarlyAsPossible,<br>
        +    CGEP_BeforePreRegAlloc,<br>
        +    CGEP_AfterPreRegAlloc,<br>
        +    CGEP_BeforePostRegAlloc,<br>
        +    CGEP_AfterPostRegAlloc,<br>
        +    CGEP_BeforePreSched2,<br>
        +    CGEP_AfterPreSched2,<br>
        +    CGEP_BeforePreEmitPass,<br>
        +    CGEP_AfterPreEmitPass,<br>
        +    CGEP_BeforePreEmitPass2,<br>
        +    CGEP_AfterPreEmitPass2,<br>
        +    CGEP_LateAsPossible<br>
        +  };<br>
        +<br>
        +  using ExtensionFn = std::function<void(TargetPassConfig
        &)>;<br>
        +<br>
         private:<br>
           PassManagerBase *PM = nullptr;<br>
           AnalysisID StartBefore = nullptr;<br>
        @@ -343,6 +363,19 @@ public:<br>
           /// Returns the CSEConfig object to use for the current
        optimization level.<br>
           virtual std::unique_ptr<CSEConfigBase> getCSEConfig()
        const;<br>
         <br>
        +  /// Add a global extension to be applied for the given Target
        TODO:<br>
        +  /// add ID and removal (cf commit<br>
        +  /// ab2300bc154f7bed43f85f74fd3fe31be71d90e0)<br>
        +  static void addGlobalExtension(const Target* Target,<br>
        +                                 CodegenExtensionPointTy CGEP,
        ExtensionFn Fn);<br>
        +<br>
        +  /// Add a pass to the PassManager if that pass is supposed to
        be run, as<br>
        +  /// determined by the StartAfter and StopAfter options. Takes
        ownership of the<br>
        +  /// pass.<br>
        +  /// @p verifyAfter   if true and adding a machine function
        pass add an extra<br>
        +  ///                  machine verification pass afterwards.<br>
        +  void addPass(Pass *P, bool verifyAfter = true);<br>
        +<br>
         protected:</p>
    </blockquote>
    <br>
    <p>Then the client code can do something like this:</p>
    <p>        const Target* target = TargetRegistry::lookupTarget(<br>
                  "x86_64-unknown-linux-gnu", error);<br>
      <br>
              TargetPassConfig::addGlobalExtension(<br>
                  target, TargetPassConfig::CGEP_BeforePreRegAlloc,<br>
                  &drti::X86DrtiTreenodePass::addSelf);<br>
    </p>
    <p>If anyone has any suggestions, please let me know</p>
    <p>Thanks,<br>
      Raoul.<br>
    </p>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">On 15/10/2020 18:51, Chen, Yuanfang
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CH2PR13MB3334C29F227CA5165FC532EB9D020@CH2PR13MB3334.namprd13.prod.outlook.com">
      <pre class="moz-quote-pre" wrap="">Looks like you want to add an out-of-tree machine pass for X86, is that right? I'm not aware of any existing mechanism to do that, but it should be straightforward to add one. 
Basically you need to
* make X86PassConfig a public API and override the interesting hooks according to your use case.
* add a new hook (say X86TargetMachine::getExtendedPassConfig) to X86TargetMachine to return an inherited X86PassConfig
* check the return value of X86TargetMachine::getExtendedPassConfig and optionally return it in X86TargetMachine::createPassConfig

Hope it helps.


-Yuanfang

-----Original Message-----
From: llvm-dev <a class="moz-txt-link-rfc2396E" href="mailto:llvm-dev-bounces@lists.llvm.org"><llvm-dev-bounces@lists.llvm.org></a> On Behalf Of Raoul Gough via llvm-dev
Sent: Thursday, October 15, 2020 12:18 AM
To: LLVM dev <a class="moz-txt-link-rfc2396E" href="mailto:llvm-dev@lists.llvm.org"><llvm-dev@lists.llvm.org></a>
Subject: [llvm-dev] Injecting customizations for TargetMachine pass

Hello llvm-dev,

I would like to be able to customise the X86TargetMachine but I couldn't 
find any proper way to do this from code external to the LLVM codebase. 
For the IR passes there are RegisterPass and RegisterStandardPasses. 
Have I overlooked an existing mechanism for extending TargetMachine 
passes or is this not really supported?

As background, I'm working on runtime inlining of calls made via 
function pointers, including C++ virtual functions. This uses a normal 
compiler like clang with some additional decoration of the IR before 
running llc to get the ahead-of-time compiled machine code. The 
decorated code can then re-compile parts of the IR at runtime by calling 
into LLJIT.

I use some low-level mechanisms to pass information between decorated 
functions alongside the normal platform ABI, and this is where I need to 
manipulate the target machine behaviour. The end result is to store some 
data in the instruction stream preceding the function return address, 
and pass a context pointer in r14.

Currently I have a workaround by adding a whole new target via 
RegisterTargetMachine. The implementation does the additional processing 
in runOnMachineFunction and delegates as much as possible to the real 
X86 target obtained via TargetRegistry::lookupTarget. This is especially 
messy because many of the TargetPassConfig virtual functions that I 
delegate to X86PassConfig are protected (e.g. addPreRegAlloc) so it's 
clearly not a "proper" way of doing what I want. The code in question is 
in 
<a class="moz-txt-link-freetext" href="https://github.com/drti/drti/blob/a204564d74ac5f8ad6946b1c96e10c84a1ffb97e/passes/drti-target.cpp">https://github.com/drti/drti/blob/a204564d74ac5f8ad6946b1c96e10c84a1ffb97e/passes/drti-target.cpp</a> 
and a general description of the runtime inliner is at 
<a class="moz-txt-link-freetext" href="https://github.com/drti/drti">https://github.com/drti/drti</a>

Can anyone suggest a better way to do the TargetMachine customization? 
If necessary I could contribute some LLVM code changes to add extension 
points but would appreciate some guidance on which way to approach it first.

Thanks,
Raoul.



_______________________________________________
LLVM Developers mailing list
<a class="moz-txt-link-abbreviated" href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>
<a class="moz-txt-link-freetext" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a>
</pre>
    </blockquote>
    <p><br>
    </p>
  </body>
</html>