Index: include/llvm/CodeGen/GlobalISel/Combiner.h =================================================================== --- /dev/null +++ include/llvm/CodeGen/GlobalISel/Combiner.h @@ -0,0 +1,43 @@ +//== ----- llvm/CodeGen/GlobalISel/Combiner.h --------------------- == // +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// This contains common code to drive combines. Combiner Passes will need to +/// setup a CombinerInfo and call combineMachineFunction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_H +#define LLVM_CODEGEN_GLOBALISEL_COMBINER_H + +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { +class MachineRegisterInfo; +class CombinerInfo; +class TargetPassConfig; +class MachineFunction; + +class Combiner { +public: + Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC); + + bool combineMachineInstrs(MachineFunction &MF); + +protected: + CombinerInfo &CInfo; + + MachineRegisterInfo *MRI = nullptr; + const TargetPassConfig *TPC; + MachineIRBuilder Builder; +}; + +} // End namespace llvm. + +#endif // LLVM_CODEGEN_GLOBALISEL_GICOMBINER_H Index: include/llvm/CodeGen/GlobalISel/CombinerHelper.h =================================================================== --- /dev/null +++ include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -0,0 +1,44 @@ +//== llvm/CodeGen/GlobalISel/CombinerHelper.h ---------------- -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// This contains common combine transformations that may be used in a combine +/// pass,or by the target elsewhere. +/// Targets can pick individual opcode transformations from the helper or use +/// tryCombine which invokes all transformations. All of the transformations return +/// true if the MachineInstruction changed and false otherwise. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H +#define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H + +namespace llvm { + +class MachineIRBuilder; +class MachineRegisterInfo; +class MachineInstr; + +class CombinerHelper { + MachineIRBuilder &Builder; + MachineRegisterInfo &MRI; + +public: + CombinerHelper(MachineIRBuilder &B); + + /// If \p MI is COPY, try to combine it. + /// Returns true if MI changed. + bool tryCombineCopy(MachineInstr &MI); + + /// Try to transform \p MI by using all of the above + /// combine functions. Returns true if changed. + bool tryCombine(MachineInstr &MI); +}; +} // namespace llvm + +#endif Index: include/llvm/CodeGen/GlobalISel/CombinerInfo.h =================================================================== --- /dev/null +++ include/llvm/CodeGen/GlobalISel/CombinerInfo.h @@ -0,0 +1,47 @@ +//===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// Interface for Targets to specify which operations are combined how and when. +/// // +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H +#define LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H + +namespace llvm { + +class LegalizerInfo; +class MachineInstr; +class MachineIRBuilder; +class MachineRegisterInfo; +// Contains information relevant to enabling/disabling various combines for a +// pass. +class CombinerInfo { +public: + CombinerInfo(bool AllowIllegalOps, bool ShouldLegalizeIllegal, + LegalizerInfo *LInfo) + : IllegalOpsAllowed(AllowIllegalOps), + LegalizeIllegalOps(ShouldLegalizeIllegal), LInfo(LInfo) { + assert(((AllowIllegalOps || !LegalizeIllegalOps) || LInfo) && + "Expecting legalizerInfo when illegalops not allowed"); + } + virtual ~CombinerInfo() = default; + /// If \p IllegalOpsAllowed is false, the CombinerHelper will make use of + /// the legalizerInfo to check for legality before each transformation. + bool IllegalOpsAllowed; // TODO: Make use of this. + + /// If \p LegalizeIllegalOps is true, the Combiner will also legalize the + /// illegal ops that are created. + bool LegalizeIllegalOps; // TODO: Make use of this. + const LegalizerInfo *LInfo; + virtual bool combine(MachineInstr &MI, MachineIRBuilder &B) const = 0; +}; +} // namespace llvm + +#endif Index: lib/CodeGen/GlobalISel/CMakeLists.txt =================================================================== --- lib/CodeGen/GlobalISel/CMakeLists.txt +++ lib/CodeGen/GlobalISel/CMakeLists.txt @@ -1,6 +1,8 @@ add_llvm_library(LLVMGlobalISel CallLowering.cpp GlobalISel.cpp + Combiner.cpp + CombinerHelper.cpp IRTranslator.cpp InstructionSelect.cpp InstructionSelector.cpp Index: lib/CodeGen/GlobalISel/Combiner.cpp =================================================================== --- /dev/null +++ lib/CodeGen/GlobalISel/Combiner.cpp @@ -0,0 +1,81 @@ +//===-- lib/CodeGen/GlobalISel/GICombiner.cpp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file constains common code to combine machine functions at generic +// level. // +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GlobalISel/Combiner.h" +#include "llvm/CodeGen/GlobalISel/CombinerInfo.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/CodeGen/GlobalISel/GISelWorkList.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "gi-combiner" + +using namespace llvm; + +Combiner::Combiner(CombinerInfo &Info, const TargetPassConfig *TPC) + : CInfo(Info), TPC(TPC) { + (void)this->TPC; // FIXME: Remove when used. +} + +bool Combiner::combineMachineInstrs(MachineFunction &MF) { + // If the ISel pipeline failed, do not bother running this pass. + // FIXME: Should this be here or in individual combiner passes. + if (MF.getProperties().hasProperty( + MachineFunctionProperties::Property::FailedISel)) + return false; + + MRI = &MF.getRegInfo(); + Builder.setMF(MF); + + DEBUG(dbgs() << "Generic MI Combiner for: " << MF.getName() << '\n'); + + MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr); + + bool MFChanged = false; + bool Changed; + + do { + // Collect all instructions. Do a post order traversal for basic blocks and + // insert with list bottom up, so while we pop_back_val, we'll traverse top + // down RPOT. + Changed = false; + GISelWorkList<512> WorkList; + for (MachineBasicBlock *MBB : post_order(&MF)) { + if (MBB->empty()) + continue; + for (auto MII = MBB->rbegin(), MIE = MBB->rend(); MII != MIE;) { + MachineInstr *CurMI = &*MII; + ++MII; + // Erase dead insts before even adding to the list. + if (isTriviallyDead(*CurMI, *MRI)) { + DEBUG(dbgs() << *CurMI << "Is dead; erasing.\n"); + CurMI->eraseFromParentAndMarkDBGValuesForRemoval(); + continue; + } + WorkList.insert(CurMI); + } + } + // Main Loop. Process the instructions here. + while (!WorkList.empty()) { + MachineInstr *CurrInst = WorkList.pop_back_val(); + DEBUG(dbgs() << "Try combining " << *CurrInst << "\n";); + Changed |= CInfo.combine(*CurrInst, Builder); + } + MFChanged |= Changed; + } while (Changed); + + return MFChanged; +} Index: lib/CodeGen/GlobalISel/CombinerHelper.cpp =================================================================== --- /dev/null +++ lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -0,0 +1,42 @@ +//== ---lib/CodeGen/GlobalISel/GICombinerHelper.cpp --------------------- == // +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/CodeGen/GlobalISel/CombinerHelper.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +#define DEBUG_TYPE "gi-combine" + +using namespace llvm; + +CombinerHelper::CombinerHelper(MachineIRBuilder &B) : + Builder(B), MRI(Builder.getMF().getRegInfo()) {} + +bool CombinerHelper::tryCombineCopy(MachineInstr &MI) { + if (MI.getOpcode() != TargetOpcode::COPY) + return false; + unsigned DstReg = MI.getOperand(0).getReg(); + unsigned SrcReg = MI.getOperand(1).getReg(); + LLT DstTy = MRI.getType(DstReg); + LLT SrcTy = MRI.getType(SrcReg); + // Simple Copy Propagation. + // a(sx) = COPY b(sx) -> Replace all uses of a with b. + if (DstTy.isValid() && SrcTy.isValid() && DstTy == SrcTy) { + MI.eraseFromParent(); + MRI.replaceRegWith(DstReg, SrcReg); + return true; + } + return false; +} + +bool CombinerHelper::tryCombine(MachineInstr &MI) { + // Right now just do the above. + return tryCombineCopy(MI); +}