//===-- X86CodeGenPassBuilder.cpp ---------------------------------*- C++ -*-=// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// This file contains X86 CodeGen pipeline builder. /// TODO: Port CodeGen passes to new pass manager. //===----------------------------------------------------------------------===// #include "X86.h" #include "X86ISelDAGToDAG.h" #include "X86TargetMachine.h" #include "llvm/CodeGen/AtomicExpand.h" #include "llvm/CodeGen/EarlyIfConversion.h" #include "llvm/CodeGen/IndirectBrExpand.h" #include "llvm/CodeGen/InterleavedAccess.h" #include "llvm/CodeGen/JMCInstrumenter.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Passes/CodeGenPassBuilder.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CodeGen.h" #include "llvm/Transforms/CFGuard.h" using namespace llvm; extern cl::opt X86EnableMachineCombinerPass; namespace { class X86CodeGenPassBuilder : public CodeGenPassBuilder { using Base = CodeGenPassBuilder; public: explicit X86CodeGenPassBuilder(X86TargetMachine &TM, const CGPassBuilderOption &Opts, PassInstrumentationCallbacks *PIC) : CodeGenPassBuilder(TM, Opts, PIC) {} void addIRPasses(PassManagerWrapper &PMW) const; void addPreISel(PassManagerWrapper &PMW) const; Error addInstSelector(PassManagerWrapper &PMW) const; void addILPOpts(PassManagerWrapper &PMW) const; void addMachineSSAOptimization(PassManagerWrapper &PMW) const; void addPreRegAlloc(PassManagerWrapper &PMW) const; // TODO(boomanaiden154): We need to add addPostFastRegAllocRewrite here once // it is available to support AMX. void addPostRegAlloc(PassManagerWrapper &PMW) const; void addPreSched2(PassManagerWrapper &PMW) const; void addPreEmitPass(PassManagerWrapper &PMW) const; void addPreEmitPass2(PassManagerWrapper &PMW) const; // TODO(boomanaiden154): We need to add addRegAssignAndRewriteOptimized here // once it is available to support AMX. void addAsmPrinter(PassManagerWrapper &PMW, CreateMCStreamer) const; }; void X86CodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const { addFunctionPass(AtomicExpandPass(TM), PMW); // We add both pass anyway and when these two passes run, one will be a // no-op based on the optimization level/attributes. addFunctionPass(X86LowerAMXIntrinsicsPass(&TM), PMW); addFunctionPass(X86LowerAMXTypePass(&TM), PMW); Base::addIRPasses(PMW); if (getOptLevel() != CodeGenOptLevel::None) { addFunctionPass(InterleavedAccessPass(TM), PMW); addFunctionPass(X86PartialReductionPass(&TM), PMW); } // Add passes that handle indirect branch removal and insertion of a retpoline // thunk. These will be a no-op unless a function subtarget has the retpoline // feature enabled. addFunctionPass(IndirectBrExpandPass(TM), PMW); // Add Control Flow Guard checks. const Triple &TT = TM.getTargetTriple(); if (TT.isOSWindows()) addFunctionPass(CFGuardPass(TT.isX86_64() ? CFGuardPass::Mechanism::Dispatch : CFGuardPass::Mechanism::Check), PMW); if (TM.Options.JMCInstrument) { flushFPMsToMPM(PMW); addModulePass(JMCInstrumenterPass(), PMW); } } void X86CodeGenPassBuilder::addPreISel(PassManagerWrapper &PMW) const { // Only add this pass for 32-bit x86 Windows. const Triple &TT = TM.getTargetTriple(); if (TT.isOSWindows() && TT.isX86_32()) { // TODO(boomanaiden154): Add X86WinEHStatePass here once it has been ported. } } Error X86CodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const { addMachineFunctionPass(X86ISelDAGToDAGPass(TM), PMW); // For ELF, cleanup any local-dynamic TLS accesses if (TM.getTargetTriple().isOSBinFormatELF() && getOptLevel() != CodeGenOptLevel::None) { addMachineFunctionPass(X86CleanupLocalDynamicTLSPass(), PMW); } addMachineFunctionPass(X86GlobalBaseRegPass(), PMW); addMachineFunctionPass(X86ArgumentStackSlotPass(), PMW); return Error::success(); } void X86CodeGenPassBuilder::addILPOpts(PassManagerWrapper &PMW) const { addMachineFunctionPass(EarlyIfConverterPass(), PMW); if (X86EnableMachineCombinerPass) { // TODO(boomanaiden154): Add the MachineCombinerPass here once it has been // ported to the new pass manager. } addMachineFunctionPass(X86CmovConversionPass(), PMW); } void X86CodeGenPassBuilder::addMachineSSAOptimization( PassManagerWrapper &PMW) const { // TODO(boomanaiden154): Add X86DomainReassignmentPass here once it has been // ported. Base::addMachineSSAOptimization(PMW); } void X86CodeGenPassBuilder::addPreRegAlloc(PassManagerWrapper &PMW) const { if (getOptLevel() != CodeGenOptLevel::None) { addMachineFunctionPass(LiveRangeShrinkPass(), PMW); addMachineFunctionPass(X86FixupSetCCPass(), PMW); addMachineFunctionPass(X86CallFrameOptimizationPass(), PMW); addMachineFunctionPass(X86AvoidStoreForwardingBlocksPass(), PMW); } addMachineFunctionPass(X86SuppressAPXForRelocationPass(), PMW); addMachineFunctionPass(X86SpeculativeLoadHardeningPass(), PMW); addMachineFunctionPass(X86FlagsCopyLoweringPass(), PMW); addMachineFunctionPass(X86DynAllocaExpanderPass(), PMW); if (getOptLevel() != CodeGenOptLevel::None) addMachineFunctionPass(X86PreTileConfigPass(), PMW); else addMachineFunctionPass(X86FastPreTileConfigPass(), PMW); } void X86CodeGenPassBuilder::addPostRegAlloc(PassManagerWrapper &PMW) const { addMachineFunctionPass(X86LowerTileCopyPass(), PMW); addMachineFunctionPass(X86FPStackifierPass(), PMW); // When -O0 is enabled, the Load Value Injection Hardening pass will fall back // to using the Speculative Execution Side Effect Suppression pass for // mitigation. This is to prevent slow downs due to // analyses needed by the LVIHardening pass when compiling at -O0. if (getOptLevel() != CodeGenOptLevel::None) { addMachineFunctionPass(X86LoadValueInjectionLoadHardeningPass(), PMW); } } void X86CodeGenPassBuilder::addPreSched2(PassManagerWrapper &PMW) const { addMachineFunctionPass(X86ExpandPseudoPass(), PMW); // TODO(boomanaiden154): Add KCFGPass here once it has been ported. } void X86CodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) const { if (getOptLevel() != CodeGenOptLevel::None) { // TODO(boomanaiden154): Add X86ExecutionDomainFixPass here once it has // been ported. addMachineFunctionPass(BreakFalseDepsPass(), PMW); } addMachineFunctionPass(X86IndirectBranchTrackingPass(), PMW); // TODO(boomanaiden154): Add X86IssueVZeroUpperPass here once it has been // ported. if (getOptLevel() != CodeGenOptLevel::None) { addMachineFunctionPass(X86FixupBWInstsPass(), PMW); // TODO(boomanaiden154): Add X86PadShortFunctionsPass here once it has been // ported. addMachineFunctionPass(X86FixupLEAsPass(), PMW); addMachineFunctionPass(X86FixupInstTuningPass(), PMW); addMachineFunctionPass(X86FixupVectorConstantsPass(), PMW); } addMachineFunctionPass(X86CompressEVEXPass(), PMW); // TODO(boomanaiden154): Add InsertX86WaitPass here once it has been ported. } void X86CodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) const { const Triple &TT = TM.getTargetTriple(); const MCAsmInfo *MAI = TM.getMCAsmInfo(); // The X86 Speculative Execution Pass must run after all control // flow graph modifying passes. As a result it was listed to run right before // the X86 Retpoline Thunks pass. The reason it must run after control flow // graph modifications is that the model of LFENCE in LLVM has to be updated // (FIXME: https://bugs.llvm.org/show_bug.cgi?id=45167). Currently the // placement of this pass was hand checked to ensure that the subsequent // passes don't move the code around the LFENCEs in a way that will hurt the // correctness of this pass. This placement has been shown to work based on // hand inspection of the codegen output. addMachineFunctionPass(X86SpeculativeExecutionSideEffectSuppressionPass(), PMW); // TODO(boomanaiden154): Add X86IndirectThunksPass here // once it has been ported. addMachineFunctionPass(X86ReturnThunksPass(), PMW); // Insert extra int3 instructions after trailing call instructions to avoid // issues in the unwinder. if (TT.isOSWindows() && TT.isX86_64()) addMachineFunctionPass(X86AvoidTrailingCallPass(), PMW); // Verify basic block incoming and outgoing cfa offset and register values and // correct CFA calculation rule where needed by inserting appropriate CFI // instructions. if (!TT.isOSDarwin() && (!TT.isOSWindows() || MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI)) { // TODO(boomanaiden154): Add CFInstrInserterPass here when it has been // ported. } if (TT.isOSWindows()) { // Identify valid longjmp targets for Windows Control Flow Guard. // TODO(boomanaiden154): Add CFGuardLongjmpPass here when it has been // ported. // Identify valid eh continuation targets for Windows EHCont Guard. // TODO(boomanaiden154): Add EHContGuardTargetsPass when it has been // ported. } addMachineFunctionPass(X86LoadValueInjectionRetHardeningPass(), PMW); // Insert pseudo probe annotation for callsite profiling // TODO(boomanaiden154): Add PseudoProberInserterPass here once it has been // ported. // KCFI indirect call checks are lowered to a bundle, and on Darwin platforms, // also CALL_RVMARKER. // TODO(boomanaiden154): Add UnpackMachineBundlesPass here once it has been // ported. // Analyzes and emits pseudos to support Win x64 Unwind V2. This pass must run // after all real instructions have been added to the epilog. if (TT.isOSWindows() && TT.isX86_64()) { addMachineFunctionPass(X86WinEHUnwindV2Pass(), PMW); } } void X86CodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW, CreateMCStreamer) const { // TODO: Add AsmPrinter. } } // namespace void X86TargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { #define GET_PASS_REGISTRY "X86PassRegistry.def" #include "llvm/Passes/TargetPassRegistry.inc" } Error X86TargetMachine::buildCodeGenPipeline( ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType FileType, const CGPassBuilderOption &Opt, PassInstrumentationCallbacks *PIC) { auto CGPB = X86CodeGenPassBuilder(*this, Opt, PIC); return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); }