Home | History | Annotate | Line # | Download | only in X86
      1 //===- X86MacroFusion.cpp - X86 Macro Fusion ------------------------------===//
      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 /// \file This file contains the X86 implementation of the DAG scheduling
     10 /// mutation to pair instructions back to back.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "X86MacroFusion.h"
     15 #include "MCTargetDesc/X86BaseInfo.h"
     16 #include "X86Subtarget.h"
     17 #include "llvm/CodeGen/MacroFusion.h"
     18 #include "llvm/CodeGen/TargetInstrInfo.h"
     19 
     20 using namespace llvm;
     21 
     22 static X86::FirstMacroFusionInstKind classifyFirst(const MachineInstr &MI) {
     23   return X86::classifyFirstOpcodeInMacroFusion(MI.getOpcode());
     24 }
     25 
     26 static X86::SecondMacroFusionInstKind classifySecond(const MachineInstr &MI) {
     27   X86::CondCode CC = X86::getCondFromBranch(MI);
     28   return X86::classifySecondCondCodeInMacroFusion(CC);
     29 }
     30 
     31 /// Check if the instr pair, FirstMI and SecondMI, should be fused
     32 /// together. Given SecondMI, when FirstMI is unspecified, then check if
     33 /// SecondMI may be part of a fused pair at all.
     34 static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
     35                                    const TargetSubtargetInfo &TSI,
     36                                    const MachineInstr *FirstMI,
     37                                    const MachineInstr &SecondMI) {
     38   const X86Subtarget &ST = static_cast<const X86Subtarget &>(TSI);
     39 
     40   // Check if this processor supports any kind of fusion.
     41   if (!(ST.hasBranchFusion() || ST.hasMacroFusion()))
     42     return false;
     43 
     44   const X86::SecondMacroFusionInstKind BranchKind = classifySecond(SecondMI);
     45 
     46   if (BranchKind == X86::SecondMacroFusionInstKind::Invalid)
     47     return false; // Second cannot be fused with anything.
     48 
     49   if (FirstMI == nullptr)
     50     return true; // We're only checking whether Second can be fused at all.
     51 
     52   const X86::FirstMacroFusionInstKind TestKind = classifyFirst(*FirstMI);
     53 
     54   if (ST.hasBranchFusion()) {
     55     // Branch fusion can merge CMP and TEST with all conditional jumps.
     56     return (TestKind == X86::FirstMacroFusionInstKind::Cmp ||
     57             TestKind == X86::FirstMacroFusionInstKind::Test);
     58   }
     59 
     60   if (ST.hasMacroFusion()) {
     61     return X86::isMacroFused(TestKind, BranchKind);
     62   }
     63 
     64   llvm_unreachable("unknown fusion type");
     65 }
     66 
     67 namespace llvm {
     68 
     69 std::unique_ptr<ScheduleDAGMutation>
     70 createX86MacroFusionDAGMutation () {
     71   return createBranchMacroFusionDAGMutation(shouldScheduleAdjacent);
     72 }
     73 
     74 } // end namespace llvm
     75