Home | History | Annotate | Download | only in llvm_gpu_backend
      1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #include "tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/dump_ir_pass.h"
     17 
     18 #include "llvm/IR/Module.h"
     19 #include "llvm/Support/FileSystem.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 #include "tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/utils.h"
     22 #include "tensorflow/compiler/xla/types.h"
     23 #include "tensorflow/core/lib/core/stringpiece.h"
     24 #include "tensorflow/core/lib/io/path.h"
     25 #include "tensorflow/core/lib/strings/stringprintf.h"
     26 #include "tensorflow/core/platform/logging.h"
     27 
     28 namespace xla {
     29 namespace gpu {
     30 
     31 // Pass which dumps the IR of a module into a file.
     32 //
     33 // Because it is implemented as a FunctionPass (IR is dumped
     34 // function-by-function) rather than as a ModulePass the resulting IR is not
     35 // valid (missing metadata, for example) but is still useful for inspection.
     36 // The pass needs to be a FunctionPass rather than a ModulePass because
     37 // inserting ModulePasses is disruptive to LLVM's pass manager.  For sequential
     38 // FunctionPasses (also SCC passes, etc) the pass manager executes the passes
     39 // sequentially on each function (SCC, etc).  Inserting a ModulePass between
     40 // FunctionPasses acts as a barrier forcing the FunctionPasses to execute fully
     41 // across all functions prior to advancing to the next pass.  For some reason
     42 // this results in different generated code resulting in an undesirable
     43 // Heisenberg effect when dumping the IR.
     44 class DumpIrPass : public llvm::FunctionPass {
     45  public:
     46   explicit DumpIrPass(const string &output_filename)
     47       : llvm::FunctionPass(id_), output_filename_(output_filename) {}
     48 
     49   bool doInitialization(llvm::Module &M) override {
     50     out_.reset(new llvm::raw_fd_ostream(llvm::StringRef(output_filename_), ec_,
     51                                         llvm::sys::fs::F_None));
     52     if (ec_) {
     53       LOG(FATAL) << "Unable to open " << output_filename_
     54                  << " to dump LLVM IR: " << ec_.message();
     55     }
     56     return false;
     57   }
     58 
     59   bool runOnFunction(llvm::Function &Function) override {
     60     Function.print(*out_);
     61     return false;
     62   }
     63 
     64   void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
     65     AU.setPreservesAll();
     66   }
     67 
     68   bool doFinalization(llvm::Module &M) override {
     69     out_->close();
     70     return false;
     71   }
     72 
     73  private:
     74   static char id_;
     75   string output_filename_;
     76   std::error_code ec_;
     77   std::unique_ptr<llvm::raw_fd_ostream> out_;
     78 };
     79 
     80 char DumpIrPass::id_ = 0;
     81 
     82 void IrDumpingPassManager::run(llvm::Module &module) {
     83   for (int i = 0; i < passes_.size(); ++i) {
     84     llvm::Pass *P = passes_[i];
     85     if (dump_ir_) {
     86       const llvm::PassInfo *PI =
     87           llvm::PassRegistry::getPassRegistry()->getPassInfo(P->getPassID());
     88       const string basename = ReplaceFilenameExtension(
     89           tensorflow::io::Basename(input_filename_),
     90           tensorflow::strings::Printf(
     91               "pass-%02d.before.%s.ll", i,
     92               (PI == nullptr ? "unknown" : PI->getPassArgument().data())));
     93       llvm::legacy::PassManager::add(
     94           new DumpIrPass(tensorflow::io::JoinPath(output_dir_, basename)));
     95     }
     96     llvm::legacy::PassManager::add(P);
     97   }
     98   passes_.clear();
     99   llvm::legacy::PassManager::run(module);
    100 }
    101 
    102 }  // namespace gpu
    103 }  // namespace xla
    104