1 //===- bolt/Passes/CMOVConversion.h ----------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This pass finds the following patterns: 10 // jcc 11 // / \ 12 // (empty) mov src, dst 13 // \ / 14 // 15 // and replaces them with: 16 // 17 // cmovcc src, dst 18 // 19 // The advantage of performing this conversion in BOLT (compared to compiler 20 // heuristic driven instruction selection) is that BOLT can use LBR 21 // misprediction information and only convert poorly predictable branches. 22 // Note that branch misprediction rate is different from branch bias. 23 // For well-predictable branches, it might be beneficial to leave jcc+mov as is 24 // from microarchitectural perspective to avoid unneeded dependencies (CMOV 25 // instruction has a dataflow dependence on flags and both operands). 26 // 27 //===----------------------------------------------------------------------===// 28 29 #ifndef BOLT_PASSES_CMOVCONVERSION_H 30 #define BOLT_PASSES_CMOVCONVERSION_H 31 32 #include "bolt/Passes/BinaryPasses.h" 33 34 namespace llvm { 35 namespace bolt { 36 37 /// Pass for folding eligible hammocks into CMOV's if profitable. 38 class CMOVConversion : public BinaryFunctionPass { 39 struct Stats { 40 /// Record how many possible cases there are. 41 uint64_t StaticPossible = 0; 42 uint64_t DynamicPossible = 0; 43 44 /// Record how many cases were converted. 45 uint64_t StaticPerformed = 0; 46 uint64_t DynamicPerformed = 0; 47 48 /// Record how many mispredictions were eliminated. 49 uint64_t PossibleMP = 0; 50 uint64_t RemovedMP = 0; 51 52 Stats operator+(const Stats &O) { 53 StaticPossible += O.StaticPossible; 54 DynamicPossible += O.DynamicPossible; 55 StaticPerformed += O.StaticPerformed; 56 DynamicPerformed += O.DynamicPerformed; 57 PossibleMP += O.PossibleMP; 58 RemovedMP += O.RemovedMP; 59 return *this; 60 } getStaticRatioStats61 double getStaticRatio() { return (double)StaticPerformed / StaticPossible; } getDynamicRatioStats62 double getDynamicRatio() { 63 return (double)DynamicPerformed / DynamicPossible; 64 } getMPRatioStats65 double getMPRatio() { return (double)RemovedMP / PossibleMP; } 66 67 void dumpTo(raw_ostream &OS); 68 }; 69 // BinaryContext-wide stats 70 Stats Global; 71 72 void runOnFunction(BinaryFunction &Function); 73 74 public: CMOVConversion()75 explicit CMOVConversion() : BinaryFunctionPass(false) {} 76 getName()77 const char *getName() const override { return "CMOV conversion"; } 78 79 Error runOnFunctions(BinaryContext &BC) override; 80 }; 81 82 } // namespace bolt 83 } // namespace llvm 84 85 #endif 86