Update prebuilt Clang to match Android kernel.
Bug: 132428451
Change-Id: I8f6e2cb23f381fc0c02ddea99b867e58e925e5be
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CSEInfo.h
new file mode 100644
index 0000000..97f3cd5
--- /dev/null
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CSEInfo.h
@@ -0,0 +1,236 @@
+//===- llvm/CodeGen/GlobalISel/CSEInfo.h ------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// Provides analysis for continuously CSEing during GISel passes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CODEGEN_GLOBALISEL_CSEINFO_H
+#define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
+#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Allocator.h"
+
+namespace llvm {
+
+/// A class that wraps MachineInstrs and derives from FoldingSetNode in order to
+/// be uniqued in a CSEMap. The tradeoff here is extra memory allocations for
+/// UniqueMachineInstr vs making MachineInstr bigger.
+class UniqueMachineInstr : public FoldingSetNode {
+ friend class GISelCSEInfo;
+ const MachineInstr *MI;
+ explicit UniqueMachineInstr(const MachineInstr *MI) : MI(MI) {}
+
+public:
+ void Profile(FoldingSetNodeID &ID);
+};
+
+// Class representing some configuration that can be done during CSE analysis.
+// Currently it only supports shouldCSE method that each pass can set.
+class CSEConfig {
+public:
+ virtual ~CSEConfig() = default;
+ // Hook for defining which Generic instructions should be CSEd.
+ // GISelCSEInfo currently only calls this hook when dealing with generic
+ // opcodes.
+ virtual bool shouldCSEOpc(unsigned Opc);
+};
+
+// TODO: Find a better place for this.
+// Commonly used for O0 config.
+class CSEConfigConstantOnly : public CSEConfig {
+public:
+ virtual ~CSEConfigConstantOnly() = default;
+ virtual bool shouldCSEOpc(unsigned Opc) override;
+};
+
+/// The CSE Analysis object.
+/// This installs itself as a delegate to the MachineFunction to track
+/// new instructions as well as deletions. It however will not be able to
+/// track instruction mutations. In such cases, recordNewInstruction should be
+/// called (for eg inside MachineIRBuilder::recordInsertion).
+/// Also because of how just the instruction can be inserted without adding any
+/// operands to the instruction, instructions are uniqued and inserted lazily.
+/// CSEInfo should assert when trying to enter an incomplete instruction into
+/// the CSEMap. There is Opcode level granularity on which instructions can be
+/// CSE'd and for now, only Generic instructions are CSEable.
+class GISelCSEInfo : public GISelChangeObserver {
+ // Make it accessible only to CSEMIRBuilder.
+ friend class CSEMIRBuilder;
+
+ BumpPtrAllocator UniqueInstrAllocator;
+ FoldingSet<UniqueMachineInstr> CSEMap;
+ MachineRegisterInfo *MRI = nullptr;
+ MachineFunction *MF = nullptr;
+ std::unique_ptr<CSEConfig> CSEOpt;
+ /// Keep a cache of UniqueInstrs for each MachineInstr. In GISel,
+ /// often instructions are mutated (while their ID has completely changed).
+ /// Whenever mutation happens, invalidate the UniqueMachineInstr for the
+ /// MachineInstr
+ DenseMap<const MachineInstr *, UniqueMachineInstr *> InstrMapping;
+
+ /// Store instructions that are not fully formed in TemporaryInsts.
+ /// Also because CSE insertion happens lazily, we can remove insts from this
+ /// list and avoid inserting and then removing from the CSEMap.
+ GISelWorkList<8> TemporaryInsts;
+
+ // Only used in asserts.
+ DenseMap<unsigned, unsigned> OpcodeHitTable;
+
+ bool isUniqueMachineInstValid(const UniqueMachineInstr &UMI) const;
+
+ void invalidateUniqueMachineInstr(UniqueMachineInstr *UMI);
+
+ UniqueMachineInstr *getNodeIfExists(FoldingSetNodeID &ID,
+ MachineBasicBlock *MBB, void *&InsertPos);
+
+ /// Allocate and construct a new UniqueMachineInstr for MI and return.
+ UniqueMachineInstr *getUniqueInstrForMI(const MachineInstr *MI);
+
+ void insertNode(UniqueMachineInstr *UMI, void *InsertPos = nullptr);
+
+ /// Get the MachineInstr(Unique) if it exists already in the CSEMap and the
+ /// same MachineBasicBlock.
+ MachineInstr *getMachineInstrIfExists(FoldingSetNodeID &ID,
+ MachineBasicBlock *MBB,
+ void *&InsertPos);
+
+ /// Use this method to allocate a new UniqueMachineInstr for MI and insert it
+ /// into the CSEMap. MI should return true for shouldCSE(MI->getOpcode())
+ void insertInstr(MachineInstr *MI, void *InsertPos = nullptr);
+
+public:
+ GISelCSEInfo() = default;
+
+ virtual ~GISelCSEInfo();
+
+ void setMF(MachineFunction &MF);
+
+ /// Records a newly created inst in a list and lazily insert it to the CSEMap.
+ /// Sometimes, this method might be called with a partially constructed
+ /// MachineInstr,
+ // (right after BuildMI without adding any operands) - and in such cases,
+ // defer the hashing of the instruction to a later stage.
+ void recordNewInstruction(MachineInstr *MI);
+
+ /// Use this callback to inform CSE about a newly fully created instruction.
+ void handleRecordedInst(MachineInstr *MI);
+
+ /// Use this callback to insert all the recorded instructions. At this point,
+ /// all of these insts need to be fully constructed and should not be missing
+ /// any operands.
+ void handleRecordedInsts();
+
+ /// Remove this inst from the CSE map. If this inst has not been inserted yet,
+ /// it will be removed from the Tempinsts list if it exists.
+ void handleRemoveInst(MachineInstr *MI);
+
+ void releaseMemory();
+
+ void setCSEConfig(std::unique_ptr<CSEConfig> Opt) { CSEOpt = std::move(Opt); }
+
+ bool shouldCSE(unsigned Opc) const;
+
+ void analyze(MachineFunction &MF);
+
+ void countOpcodeHit(unsigned Opc);
+
+ void print();
+
+ // Observer API
+ void erasingInstr(MachineInstr &MI) override;
+ void createdInstr(MachineInstr &MI) override;
+ void changingInstr(MachineInstr &MI) override;
+ void changedInstr(MachineInstr &MI) override;
+};
+
+class TargetRegisterClass;
+class RegisterBank;
+
+// Simple builder class to easily profile properties about MIs.
+class GISelInstProfileBuilder {
+ FoldingSetNodeID &ID;
+ const MachineRegisterInfo &MRI;
+
+public:
+ GISelInstProfileBuilder(FoldingSetNodeID &ID, const MachineRegisterInfo &MRI)
+ : ID(ID), MRI(MRI) {}
+ // Profiling methods.
+ const GISelInstProfileBuilder &addNodeIDOpcode(unsigned Opc) const;
+ const GISelInstProfileBuilder &addNodeIDRegType(const LLT &Ty) const;
+ const GISelInstProfileBuilder &addNodeIDRegType(const unsigned) const;
+
+ const GISelInstProfileBuilder &
+ addNodeIDRegType(const TargetRegisterClass *RC) const;
+ const GISelInstProfileBuilder &addNodeIDRegType(const RegisterBank *RB) const;
+
+ const GISelInstProfileBuilder &addNodeIDRegNum(unsigned Reg) const;
+
+ const GISelInstProfileBuilder &addNodeIDImmediate(int64_t Imm) const;
+ const GISelInstProfileBuilder &
+ addNodeIDMBB(const MachineBasicBlock *MBB) const;
+
+ const GISelInstProfileBuilder &
+ addNodeIDMachineOperand(const MachineOperand &MO) const;
+
+ const GISelInstProfileBuilder &addNodeIDFlag(unsigned Flag) const;
+ const GISelInstProfileBuilder &addNodeID(const MachineInstr *MI) const;
+};
+
+/// Simple wrapper that does the following.
+/// 1) Lazily evaluate the MachineFunction to compute CSEable instructions.
+/// 2) Allows configuration of which instructions are CSEd through CSEConfig
+/// object. Provides a method called get which takes a CSEConfig object.
+class GISelCSEAnalysisWrapper {
+ GISelCSEInfo Info;
+ MachineFunction *MF = nullptr;
+ bool AlreadyComputed = false;
+
+public:
+ /// Takes a CSEConfig object that defines what opcodes get CSEd.
+ /// If CSEConfig is already set, and the CSE Analysis has been preserved,
+ /// it will not use the new CSEOpt(use Recompute to force using the new
+ /// CSEOpt).
+ GISelCSEInfo &get(std::unique_ptr<CSEConfig> CSEOpt, bool ReCompute = false);
+ void setMF(MachineFunction &MFunc) { MF = &MFunc; }
+ void setComputed(bool Computed) { AlreadyComputed = Computed; }
+ void releaseMemory() { Info.releaseMemory(); }
+};
+
+/// The actual analysis pass wrapper.
+class GISelCSEAnalysisWrapperPass : public MachineFunctionPass {
+ GISelCSEAnalysisWrapper Wrapper;
+
+public:
+ static char ID;
+ GISelCSEAnalysisWrapperPass() : MachineFunctionPass(ID) {
+ initializeGISelCSEAnalysisWrapperPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ const GISelCSEAnalysisWrapper &getCSEWrapper() const { return Wrapper; }
+ GISelCSEAnalysisWrapper &getCSEWrapper() { return Wrapper; }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ void releaseMemory() override {
+ Wrapper.releaseMemory();
+ Wrapper.setComputed(false);
+ }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h
new file mode 100644
index 0000000..4f95335
--- /dev/null
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h
@@ -0,0 +1,109 @@
+//===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- 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 implements a version of MachineIRBuilder which CSEs insts within
+/// a MachineBasicBlock.
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
+#define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+
+namespace llvm {
+
+/// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
+/// Eg usage.
+///
+///
+/// GISelCSEInfo *Info =
+/// &getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEInfo(); CSEMIRBuilder
+/// CB(Builder.getState()); CB.setCSEInfo(Info); auto A = CB.buildConstant(s32,
+/// 42); auto B = CB.buildConstant(s32, 42); assert(A == B); unsigned CReg =
+/// MRI.createGenericVirtualRegister(s32); auto C = CB.buildConstant(CReg, 42);
+/// assert(C->getOpcode() == TargetOpcode::COPY);
+/// Explicitly passing in a register would materialize a copy if possible.
+/// CSEMIRBuilder also does trivial constant folding for binary ops.
+class CSEMIRBuilder : public MachineIRBuilder {
+
+ /// Returns true if A dominates B (within the same basic block).
+ /// Both iterators must be in the same basic block.
+ //
+ // TODO: Another approach for checking dominance is having two iterators and
+ // making them go towards each other until they meet or reach begin/end. Which
+ // approach is better? Should this even change dynamically? For G_CONSTANTS
+ // most of which will be at the top of the BB, the top down approach would be
+ // a better choice. Does IRTranslator placing constants at the beginning still
+ // make sense? Should this change based on Opcode?
+ bool dominates(MachineBasicBlock::const_iterator A,
+ MachineBasicBlock::const_iterator B) const;
+
+ /// For given ID, find a machineinstr in the CSE Map. If found, check if it
+ /// dominates the current insertion point and if not, move it just before the
+ /// current insertion point and return it. If not found, return Null
+ /// MachineInstrBuilder.
+ MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID,
+ void *&NodeInsertPos);
+ /// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is
+ /// safe to CSE.
+ bool canPerformCSEForOpc(unsigned Opc) const;
+
+ void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const;
+
+ void profileDstOps(ArrayRef<DstOp> Ops, GISelInstProfileBuilder &B) const {
+ for (const DstOp &Op : Ops)
+ profileDstOp(Op, B);
+ }
+
+ void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const;
+
+ void profileSrcOps(ArrayRef<SrcOp> Ops, GISelInstProfileBuilder &B) const {
+ for (const SrcOp &Op : Ops)
+ profileSrcOp(Op, B);
+ }
+
+ void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const;
+
+ void profileEverything(unsigned Opc, ArrayRef<DstOp> DstOps,
+ ArrayRef<SrcOp> SrcOps, Optional<unsigned> Flags,
+ GISelInstProfileBuilder &B) const;
+
+ // Takes a MachineInstrBuilder and inserts it into the CSEMap using the
+ // NodeInsertPos.
+ MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos);
+
+ // If we have can CSE an instruction, but still need to materialize to a VReg,
+ // we emit a copy from the CSE'd inst to the VReg.
+ MachineInstrBuilder generateCopiesIfRequired(ArrayRef<DstOp> DstOps,
+ MachineInstrBuilder &MIB);
+
+ // If we have can CSE an instruction, but still need to materialize to a VReg,
+ // check if we can generate copies. It's not possible to return a single MIB,
+ // while emitting copies to multiple vregs.
+ bool checkCopyToDefsPossible(ArrayRef<DstOp> DstOps);
+
+public:
+ // Pull in base class constructors.
+ using MachineIRBuilder::MachineIRBuilder;
+ // Unhide buildInstr
+ MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
+ ArrayRef<SrcOp> SrcOps,
+ Optional<unsigned> Flag = None) override;
+ // Bring in the other overload from the base class.
+ using MachineIRBuilder::buildConstant;
+
+ MachineInstrBuilder buildConstant(const DstOp &Res,
+ const ConstantInt &Val) override;
+
+ // Bring in the other overload from the base class.
+ using MachineIRBuilder::buildFConstant;
+ MachineInstrBuilder buildFConstant(const DstOp &Res,
+ const ConstantFP &Val) override;
+};
+} // namespace llvm
+#endif
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CallLowering.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CallLowering.h
index 32980ce..9b72b70 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CallLowering.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
@@ -40,6 +39,7 @@
class CallLowering {
const TargetLowering *TLI;
+ virtual void anchor();
public:
struct ArgInfo {
unsigned Reg;
@@ -108,6 +108,9 @@
MachineIRBuilder &MIRBuilder;
MachineRegisterInfo &MRI;
CCAssignFn *AssignFn;
+
+ private:
+ virtual void anchor();
};
protected:
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Combiner.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Combiner.h
index fa49e8c..12a1f97 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Combiner.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Combiner.h
@@ -1,9 +1,8 @@
//== ----- 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.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -21,31 +20,25 @@
namespace llvm {
class MachineRegisterInfo;
class CombinerInfo;
+class GISelCSEInfo;
class TargetPassConfig;
class MachineFunction;
-class CombinerChangeObserver {
-public:
- virtual ~CombinerChangeObserver() {}
-
- /// An instruction was erased.
- virtual void erasedInstr(MachineInstr &MI) = 0;
- /// An instruction was created and inseerted into the function.
- virtual void createdInstr(MachineInstr &MI) = 0;
-};
-
class Combiner {
public:
Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC);
- bool combineMachineInstrs(MachineFunction &MF);
+ /// If CSEInfo is not null, then the Combiner will setup observer for
+ /// CSEInfo and instantiate a CSEMIRBuilder. Pass nullptr if CSE is not
+ /// needed.
+ bool combineMachineInstrs(MachineFunction &MF, GISelCSEInfo *CSEInfo);
protected:
CombinerInfo &CInfo;
MachineRegisterInfo *MRI = nullptr;
const TargetPassConfig *TPC;
- MachineIRBuilder Builder;
+ std::unique_ptr<MachineIRBuilder> Builder;
};
} // End namespace llvm.
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index ee67f90..ee30ba9 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -1,9 +1,8 @@
-//== llvm/CodeGen/GlobalISel/CombinerHelper.h -------------- -*- C++ -*-==//
+//===-- 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.
+// 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
//
//===--------------------------------------------------------------------===//
//
@@ -20,21 +19,27 @@
namespace llvm {
-class CombinerChangeObserver;
+class GISelChangeObserver;
class MachineIRBuilder;
class MachineRegisterInfo;
class MachineInstr;
+class MachineOperand;
class CombinerHelper {
MachineIRBuilder &Builder;
MachineRegisterInfo &MRI;
- CombinerChangeObserver &Observer;
-
- void eraseInstr(MachineInstr &MI);
- void scheduleForVisit(MachineInstr &MI);
+ GISelChangeObserver &Observer;
public:
- CombinerHelper(CombinerChangeObserver &Observer, MachineIRBuilder &B);
+ CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B);
+
+ /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes
+ void replaceRegWith(MachineRegisterInfo &MRI, unsigned FromReg, unsigned ToReg) const;
+
+ /// Replace a single register operand with a new register and inform the
+ /// observer of the changes.
+ void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp,
+ unsigned ToReg) const;
/// If \p MI is COPY, try to combine it.
/// Returns true if MI changed.
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerInfo.h
index 98c5b98..3b09a8e 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerInfo.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/CombinerInfo.h
@@ -1,9 +1,8 @@
//===- 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.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -17,7 +16,7 @@
#include <cassert>
namespace llvm {
-class CombinerChangeObserver;
+class GISelChangeObserver;
class LegalizerInfo;
class MachineInstr;
class MachineIRBuilder;
@@ -43,7 +42,18 @@
/// illegal ops that are created.
bool LegalizeIllegalOps; // TODO: Make use of this.
const LegalizerInfo *LInfo;
- virtual bool combine(CombinerChangeObserver &Observer, MachineInstr &MI,
+
+ /// Attempt to combine instructions using MI as the root.
+ ///
+ /// Use Observer to report the creation, modification, and erasure of
+ /// instructions. GISelChangeObserver will automatically report certain
+ /// kinds of operations. These operations are:
+ /// * Instructions that are newly inserted into the MachineFunction
+ /// * Instructions that are erased from the MachineFunction.
+ ///
+ /// However, it is important to report instruction modification and this is
+ /// not automatic.
+ virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI,
MachineIRBuilder &B) const = 0;
};
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
index 8d61f9a..e817d9b 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h --*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
@@ -15,91 +14,20 @@
namespace llvm {
-static Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1,
- const unsigned Op2,
- const MachineRegisterInfo &MRI) {
- auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI);
- auto MaybeOp2Cst = getConstantVRegVal(Op2, MRI);
- if (MaybeOp1Cst && MaybeOp2Cst) {
- LLT Ty = MRI.getType(Op1);
- APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true);
- APInt C2(Ty.getSizeInBits(), *MaybeOp2Cst, true);
- switch (Opcode) {
- default:
- break;
- case TargetOpcode::G_ADD:
- return C1 + C2;
- case TargetOpcode::G_AND:
- return C1 & C2;
- case TargetOpcode::G_ASHR:
- return C1.ashr(C2);
- case TargetOpcode::G_LSHR:
- return C1.lshr(C2);
- case TargetOpcode::G_MUL:
- return C1 * C2;
- case TargetOpcode::G_OR:
- return C1 | C2;
- case TargetOpcode::G_SHL:
- return C1 << C2;
- case TargetOpcode::G_SUB:
- return C1 - C2;
- case TargetOpcode::G_XOR:
- return C1 ^ C2;
- case TargetOpcode::G_UDIV:
- if (!C2.getBoolValue())
- break;
- return C1.udiv(C2);
- case TargetOpcode::G_SDIV:
- if (!C2.getBoolValue())
- break;
- return C1.sdiv(C2);
- case TargetOpcode::G_UREM:
- if (!C2.getBoolValue())
- break;
- return C1.urem(C2);
- case TargetOpcode::G_SREM:
- if (!C2.getBoolValue())
- break;
- return C1.srem(C2);
- }
- }
- return None;
-}
-
/// An MIRBuilder which does trivial constant folding of binary ops.
/// Calls to buildInstr will also try to constant fold binary ops.
-class ConstantFoldingMIRBuilder
- : public FoldableInstructionsBuilder<ConstantFoldingMIRBuilder> {
+class ConstantFoldingMIRBuilder : public MachineIRBuilder {
public:
// Pull in base class constructors.
- using FoldableInstructionsBuilder<
- ConstantFoldingMIRBuilder>::FoldableInstructionsBuilder;
- // Unhide buildInstr
- using FoldableInstructionsBuilder<ConstantFoldingMIRBuilder>::buildInstr;
+ using MachineIRBuilder::MachineIRBuilder;
- // Implement buildBinaryOp required by FoldableInstructionsBuilder which
- // tries to constant fold.
- MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst,
- unsigned Src0, unsigned Src1) {
- validateBinaryOp(Dst, Src0, Src1);
- auto MaybeCst = ConstantFoldBinOp(Opcode, Src0, Src1, getMF().getRegInfo());
- if (MaybeCst)
- return buildConstant(Dst, MaybeCst->getSExtValue());
- return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1);
- }
-
- template <typename DstTy, typename UseArg1Ty, typename UseArg2Ty>
- MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, UseArg1Ty &&Arg1,
- UseArg2Ty &&Arg2) {
- unsigned Dst = getDestFromArg(Ty);
- return buildInstr(Opc, Dst, getRegFromArg(std::forward<UseArg1Ty>(Arg1)),
- getRegFromArg(std::forward<UseArg2Ty>(Arg2)));
- }
+ virtual ~ConstantFoldingMIRBuilder() = default;
// Try to provide an overload for buildInstr for binary ops in order to
// constant fold.
- MachineInstrBuilder buildInstr(unsigned Opc, unsigned Dst, unsigned Src0,
- unsigned Src1) {
+ MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
+ ArrayRef<SrcOp> SrcOps,
+ Optional<unsigned> Flags = None) override {
switch (Opc) {
default:
break;
@@ -116,19 +44,18 @@
case TargetOpcode::G_SDIV:
case TargetOpcode::G_UREM:
case TargetOpcode::G_SREM: {
- return buildBinaryOp(Opc, Dst, Src0, Src1);
+ assert(DstOps.size() == 1 && "Invalid dst ops");
+ assert(SrcOps.size() == 2 && "Invalid src ops");
+ const DstOp &Dst = DstOps[0];
+ const SrcOp &Src0 = SrcOps[0];
+ const SrcOp &Src1 = SrcOps[1];
+ if (auto MaybeCst =
+ ConstantFoldBinOp(Opc, Src0.getReg(), Src1.getReg(), *getMRI()))
+ return buildConstant(Dst, MaybeCst->getSExtValue());
+ break;
}
}
- return buildInstr(Opc).addDef(Dst).addUse(Src0).addUse(Src1);
- }
-
- // Fallback implementation of buildInstr.
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
- UseArgsTy &&... Args) {
- auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
- addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
- return MIB;
+ return MachineIRBuilder::buildInstr(Opc, DstOps, SrcOps);
}
};
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h
new file mode 100644
index 0000000..e5691cb
--- /dev/null
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h
@@ -0,0 +1,117 @@
+//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// This contains common code to allow clients to notify changes to machine
+/// instr.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
+#define LLVM_CODEGEN_GLOBALISEL_GISELCHANGEOBSERVER_H
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/CodeGen/MachineFunction.h"
+
+namespace llvm {
+class MachineInstr;
+class MachineRegisterInfo;
+
+/// Abstract class that contains various methods for clients to notify about
+/// changes. This should be the preferred way for APIs to notify changes.
+/// Typically calling erasingInstr/createdInstr multiple times should not affect
+/// the result. The observer would likely need to check if it was already
+/// notified earlier (consider using GISelWorkList).
+class GISelChangeObserver {
+ SmallPtrSet<MachineInstr *, 4> ChangingAllUsesOfReg;
+
+public:
+ virtual ~GISelChangeObserver() {}
+
+ /// An instruction is about to be erased.
+ virtual void erasingInstr(MachineInstr &MI) = 0;
+
+ /// An instruction has been created and inserted into the function.
+ /// Note that the instruction might not be a fully fledged instruction at this
+ /// point and won't be if the MachineFunction::Delegate is calling it. This is
+ /// because the delegate only sees the construction of the MachineInstr before
+ /// operands have been added.
+ virtual void createdInstr(MachineInstr &MI) = 0;
+
+ /// This instruction is about to be mutated in some way.
+ virtual void changingInstr(MachineInstr &MI) = 0;
+
+ /// This instruction was mutated in some way.
+ virtual void changedInstr(MachineInstr &MI) = 0;
+
+ /// All the instructions using the given register are being changed.
+ /// For convenience, finishedChangingAllUsesOfReg() will report the completion
+ /// of the changes. The use list may change between this call and
+ /// finishedChangingAllUsesOfReg().
+ void changingAllUsesOfReg(const MachineRegisterInfo &MRI, unsigned Reg);
+ /// All instructions reported as changing by changingAllUsesOfReg() have
+ /// finished being changed.
+ void finishedChangingAllUsesOfReg();
+
+};
+
+/// Simple wrapper observer that takes several observers, and calls
+/// each one for each event. If there are multiple observers (say CSE,
+/// Legalizer, Combiner), it's sufficient to register this to the machine
+/// function as the delegate.
+class GISelObserverWrapper : public MachineFunction::Delegate,
+ public GISelChangeObserver {
+ SmallVector<GISelChangeObserver *, 4> Observers;
+
+public:
+ GISelObserverWrapper() = default;
+ GISelObserverWrapper(ArrayRef<GISelChangeObserver *> Obs)
+ : Observers(Obs.begin(), Obs.end()) {}
+ // Adds an observer.
+ void addObserver(GISelChangeObserver *O) { Observers.push_back(O); }
+ // Removes an observer from the list and does nothing if observer is not
+ // present.
+ void removeObserver(GISelChangeObserver *O) {
+ auto It = std::find(Observers.begin(), Observers.end(), O);
+ if (It != Observers.end())
+ Observers.erase(It);
+ }
+ // API for Observer.
+ void erasingInstr(MachineInstr &MI) override {
+ for (auto &O : Observers)
+ O->erasingInstr(MI);
+ }
+ void createdInstr(MachineInstr &MI) override {
+ for (auto &O : Observers)
+ O->createdInstr(MI);
+ }
+ void changingInstr(MachineInstr &MI) override {
+ for (auto &O : Observers)
+ O->changingInstr(MI);
+ }
+ void changedInstr(MachineInstr &MI) override {
+ for (auto &O : Observers)
+ O->changedInstr(MI);
+ }
+ // API for MachineFunction::Delegate
+ void MF_HandleInsertion(MachineInstr &MI) override { createdInstr(MI); }
+ void MF_HandleRemoval(MachineInstr &MI) override { erasingInstr(MI); }
+};
+
+/// A simple RAII based CSEInfo installer.
+/// Use this in a scope to install a delegate to the MachineFunction and reset
+/// it at the end of the scope.
+class RAIIDelegateInstaller {
+ MachineFunction &MF;
+ MachineFunction::Delegate *Delegate;
+
+public:
+ RAIIDelegateInstaller(MachineFunction &MF, MachineFunction::Delegate *Del);
+ ~RAIIDelegateInstaller();
+};
+
+} // namespace llvm
+#endif
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelWorkList.h
index 167905d..626a666 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelWorkList.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/GISelWorkList.h
@@ -1,9 +1,8 @@
//===- GISelWorkList.h - Worklist for GISel passes ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -12,38 +11,42 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/Debug.h"
namespace llvm {
class MachineInstr;
+class MachineFunction;
-// Worklist which mostly works similar to InstCombineWorkList, but on MachineInstrs.
-// The main difference with something like a SetVector is that erasing an element doesn't
-// move all elements over one place - instead just nulls out the element of the vector.
-// FIXME: Does it make sense to factor out common code with the instcombinerWorkList?
+// Worklist which mostly works similar to InstCombineWorkList, but on
+// MachineInstrs. The main difference with something like a SetVector is that
+// erasing an element doesn't move all elements over one place - instead just
+// nulls out the element of the vector.
+//
+// FIXME: Does it make sense to factor out common code with the
+// instcombinerWorkList?
template<unsigned N>
class GISelWorkList {
- SmallVector<MachineInstr*, N> Worklist;
- DenseMap<MachineInstr*, unsigned> WorklistMap;
+ SmallVector<MachineInstr *, N> Worklist;
+ DenseMap<MachineInstr *, unsigned> WorklistMap;
public:
- GISelWorkList() = default;
+ GISelWorkList() : WorklistMap(N) {}
bool empty() const { return WorklistMap.empty(); }
unsigned size() const { return WorklistMap.size(); }
- /// Add - Add the specified instruction to the worklist if it isn't already
- /// in it.
+ /// Add the specified instruction to the worklist if it isn't already in it.
void insert(MachineInstr *I) {
- if (WorklistMap.try_emplace(I, Worklist.size()).second) {
+ if (WorklistMap.try_emplace(I, Worklist.size()).second)
Worklist.push_back(I);
- }
}
- /// Remove - remove I from the worklist if it exists.
- void remove(MachineInstr *I) {
+ /// Remove I from the worklist if it exists.
+ void remove(const MachineInstr *I) {
auto It = WorklistMap.find(I);
if (It == WorklistMap.end()) return; // Not in worklist.
@@ -53,6 +56,11 @@
WorklistMap.erase(It);
}
+ void clear() {
+ Worklist.clear();
+ WorklistMap.clear();
+ }
+
MachineInstr *pop_back_val() {
MachineInstr *I;
do {
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 2498ee9..c75d823 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
@@ -21,11 +20,11 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Types.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/Support/Allocator.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/Support/Allocator.h"
#include <memory>
#include <utility>
@@ -217,6 +216,17 @@
bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op,
MachineIRBuilder &MIRBuilder);
+ /// Helper function for translateSimpleIntrinsic.
+ /// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a
+ /// simple intrinsic (ceil, fabs, etc.). Otherwise, returns
+ /// Intrinsic::not_intrinsic.
+ unsigned getSimpleIntrinsicOpcode(Intrinsic::ID ID);
+
+ /// Translates the intrinsics defined in getSimpleIntrinsicOpcode.
+ /// \return true if the translation succeeded.
+ bool translateSimpleIntrinsic(const CallInst &CI, Intrinsic::ID ID,
+ MachineIRBuilder &MIRBuilder);
+
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MachineIRBuilder &MIRBuilder);
@@ -242,6 +252,8 @@
bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateCallBr(const User &U, MachineIRBuilder &MIRBuilder);
+
bool translateLandingPad(const User &U, MachineIRBuilder &MIRBuilder);
/// Translate one of LLVM's cast instructions into MachineInstrs, with the
@@ -300,6 +312,8 @@
bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateFNeg(const User &U, MachineIRBuilder &MIRBuilder);
+
bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder);
}
@@ -442,11 +456,13 @@
// I.e., compared to regular MIBuilder, this one also inserts the instruction
// in the current block, it can creates block, etc., basically a kind of
// IRBuilder, but for Machine IR.
- MachineIRBuilder CurBuilder;
+ // CSEMIRBuilder CurBuilder;
+ std::unique_ptr<MachineIRBuilder> CurBuilder;
// Builder set to the entry block (just after ABI lowering instructions). Used
// as a convenient location for Constants.
- MachineIRBuilder EntryBuilder;
+ // CSEMIRBuilder EntryBuilder;
+ std::unique_ptr<MachineIRBuilder> EntryBuilder;
// The MachineFunction currently being translated.
MachineFunction *MF;
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelect.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelect.h
index 01521c4..1af46e0 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelect.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelect.h
@@ -1,9 +1,8 @@
//== llvm/CodeGen/GlobalISel/InstructionSelect.h -----------------*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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 describes the interface of the MachineFunctionPass
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index 471def7..e4d05a5 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/InstructionSelector.h ------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
index 2003a79..87ef2f8 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
index 8735876..e7680e1 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
@@ -1,9 +1,8 @@
-//===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h --===========//
+//===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
// This file contains some helper functions which try to cleanup artifacts
@@ -14,12 +13,14 @@
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
+#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "legalizer"
+using namespace llvm::MIPatternMatch;
namespace llvm {
class LegalizationArtifactCombiner {
@@ -36,15 +37,29 @@
SmallVectorImpl<MachineInstr *> &DeadInsts) {
if (MI.getOpcode() != TargetOpcode::G_ANYEXT)
return false;
- if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC,
- MI.getOperand(1).getReg(), MRI)) {
+
+ Builder.setInstr(MI);
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
+
+ // aext(trunc x) - > aext/copy/trunc x
+ unsigned TruncSrc;
+ if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
- unsigned DstReg = MI.getOperand(0).getReg();
- unsigned SrcReg = DefMI->getOperand(1).getReg();
- Builder.setInstr(MI);
- // We get a copy/trunc/extend depending on the sizes
- Builder.buildAnyExtOrTrunc(DstReg, SrcReg);
- markInstAndDefDead(MI, *DefMI, DeadInsts);
+ Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
+ markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
+ return true;
+ }
+
+ // aext([asz]ext x) -> [asz]ext x
+ unsigned ExtSrc;
+ MachineInstr *ExtMI;
+ if (mi_match(SrcReg, MRI,
+ m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
+ m_GSExt(m_Reg(ExtSrc)),
+ m_GZExt(m_Reg(ExtSrc)))))) {
+ Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
+ markInstAndDefDead(MI, *ExtMI, DeadInsts);
return true;
}
return tryFoldImplicitDef(MI, DeadInsts);
@@ -55,24 +70,25 @@
if (MI.getOpcode() != TargetOpcode::G_ZEXT)
return false;
- if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC,
- MI.getOperand(1).getReg(), MRI)) {
- unsigned DstReg = MI.getOperand(0).getReg();
+
+ Builder.setInstr(MI);
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
+
+ // zext(trunc x) - > and (aext/copy/trunc x), mask
+ unsigned TruncSrc;
+ if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
LLT DstTy = MRI.getType(DstReg);
if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
- isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
+ isConstantUnsupported(DstTy))
return false;
LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
- Builder.setInstr(MI);
- unsigned ZExtSrc = MI.getOperand(1).getReg();
- LLT ZExtSrcTy = MRI.getType(ZExtSrc);
- APInt Mask = APInt::getAllOnesValue(ZExtSrcTy.getSizeInBits());
- auto MaskCstMIB = Builder.buildConstant(DstTy, Mask.getZExtValue());
- unsigned TruncSrc = DefMI->getOperand(1).getReg();
- // We get a copy/trunc/extend depending on the sizes
- auto SrcCopyOrTrunc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc);
- Builder.buildAnd(DstReg, SrcCopyOrTrunc, MaskCstMIB);
- markInstAndDefDead(MI, *DefMI, DeadInsts);
+ LLT SrcTy = MRI.getType(SrcReg);
+ APInt Mask = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits());
+ auto MIBMask = Builder.buildConstant(DstTy, Mask.getZExtValue());
+ Builder.buildAnd(DstReg, Builder.buildAnyExtOrTrunc(DstTy, TruncSrc),
+ MIBMask);
+ markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
return true;
}
return tryFoldImplicitDef(MI, DeadInsts);
@@ -83,33 +99,36 @@
if (MI.getOpcode() != TargetOpcode::G_SEXT)
return false;
- if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC,
- MI.getOperand(1).getReg(), MRI)) {
- unsigned DstReg = MI.getOperand(0).getReg();
+
+ Builder.setInstr(MI);
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
+
+ // sext(trunc x) - > ashr (shl (aext/copy/trunc x), c), c
+ unsigned TruncSrc;
+ if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
LLT DstTy = MRI.getType(DstReg);
- if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) ||
- isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) ||
- isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
+ // Guess on the RHS shift amount type, which should be re-legalized if
+ // applicable.
+ if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy, DstTy}}) ||
+ isInstUnsupported({TargetOpcode::G_ASHR, {DstTy, DstTy}}) ||
+ isConstantUnsupported(DstTy))
return false;
LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
- Builder.setInstr(MI);
- unsigned SExtSrc = MI.getOperand(1).getReg();
- LLT SExtSrcTy = MRI.getType(SExtSrc);
- unsigned SizeDiff = DstTy.getSizeInBits() - SExtSrcTy.getSizeInBits();
- auto SizeDiffMIB = Builder.buildConstant(DstTy, SizeDiff);
- unsigned TruncSrcReg = DefMI->getOperand(1).getReg();
- // We get a copy/trunc/extend depending on the sizes
- auto SrcCopyExtOrTrunc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrcReg);
- auto ShlMIB = Builder.buildInstr(TargetOpcode::G_SHL, DstTy,
- SrcCopyExtOrTrunc, SizeDiffMIB);
- Builder.buildInstr(TargetOpcode::G_ASHR, DstReg, ShlMIB, SizeDiffMIB);
- markInstAndDefDead(MI, *DefMI, DeadInsts);
+ LLT SrcTy = MRI.getType(SrcReg);
+ unsigned ShAmt = DstTy.getScalarSizeInBits() - SrcTy.getScalarSizeInBits();
+ auto MIBShAmt = Builder.buildConstant(DstTy, ShAmt);
+ auto MIBShl = Builder.buildInstr(
+ TargetOpcode::G_SHL, {DstTy},
+ {Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), MIBShAmt});
+ Builder.buildInstr(TargetOpcode::G_ASHR, {DstReg}, {MIBShl, MIBShAmt});
+ markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
return true;
}
return tryFoldImplicitDef(MI, DeadInsts);
}
- /// Try to fold sb = EXTEND (G_IMPLICIT_DEF sa) -> sb = G_IMPLICIT_DEF
+ /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
bool tryFoldImplicitDef(MachineInstr &MI,
SmallVectorImpl<MachineInstr *> &DeadInsts) {
unsigned Opcode = MI.getOpcode();
@@ -119,19 +138,41 @@
if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
MI.getOperand(1).getReg(), MRI)) {
+ Builder.setInstr(MI);
unsigned DstReg = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(DstReg);
- if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
- return false;
- LLVM_DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;);
- Builder.setInstr(MI);
- Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, DstReg);
+
+ if (Opcode == TargetOpcode::G_ANYEXT) {
+ // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
+ if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
+ return false;
+ LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
+ Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
+ } else {
+ // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
+ // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
+ if (isConstantUnsupported(DstTy))
+ return false;
+ LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
+ Builder.buildConstant(DstReg, 0);
+ }
+
markInstAndDefDead(MI, *DefMI, DeadInsts);
return true;
}
return false;
}
+ static unsigned getMergeOpcode(LLT OpTy, LLT DestTy) {
+ if (OpTy.isVector() && DestTy.isVector())
+ return TargetOpcode::G_CONCAT_VECTORS;
+
+ if (OpTy.isVector() && !DestTy.isVector())
+ return TargetOpcode::G_BUILD_VECTOR;
+
+ return TargetOpcode::G_MERGE_VALUES;
+ }
+
bool tryCombineMerges(MachineInstr &MI,
SmallVectorImpl<MachineInstr *> &DeadInsts) {
@@ -139,8 +180,14 @@
return false;
unsigned NumDefs = MI.getNumOperands() - 1;
- MachineInstr *MergeI = getOpcodeDef(TargetOpcode::G_MERGE_VALUES,
- MI.getOperand(NumDefs).getReg(), MRI);
+
+ LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg());
+ LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
+
+ unsigned MergingOpcode = getMergeOpcode(OpTy, DestTy);
+ MachineInstr *MergeI =
+ getOpcodeDef(MergingOpcode, MI.getOperand(NumDefs).getReg(), MRI);
+
if (!MergeI)
return false;
@@ -206,6 +253,65 @@
return true;
}
+ static bool isMergeLikeOpcode(unsigned Opc) {
+ switch (Opc) {
+ case TargetOpcode::G_MERGE_VALUES:
+ case TargetOpcode::G_BUILD_VECTOR:
+ case TargetOpcode::G_CONCAT_VECTORS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool tryCombineExtract(MachineInstr &MI,
+ SmallVectorImpl<MachineInstr *> &DeadInsts) {
+ assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
+
+ // Try to use the source registers from a G_MERGE_VALUES
+ //
+ // %2 = G_MERGE_VALUES %0, %1
+ // %3 = G_EXTRACT %2, N
+ // =>
+ //
+ // for N < %2.getSizeInBits() / 2
+ // %3 = G_EXTRACT %0, N
+ //
+ // for N >= %2.getSizeInBits() / 2
+ // %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
+
+ unsigned Src = lookThroughCopyInstrs(MI.getOperand(1).getReg());
+ MachineInstr *MergeI = MRI.getVRegDef(Src);
+ if (!MergeI || !isMergeLikeOpcode(MergeI->getOpcode()))
+ return false;
+
+ LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
+ LLT SrcTy = MRI.getType(Src);
+
+ // TODO: Do we need to check if the resulting extract is supported?
+ unsigned ExtractDstSize = DstTy.getSizeInBits();
+ unsigned Offset = MI.getOperand(2).getImm();
+ unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
+ unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
+ unsigned MergeSrcIdx = Offset / MergeSrcSize;
+
+ // Compute the offset of the last bit the extract needs.
+ unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
+
+ // Can't handle the case where the extract spans multiple inputs.
+ if (MergeSrcIdx != EndMergeSrcIdx)
+ return false;
+
+ // TODO: We could modify MI in place in most cases.
+ Builder.setInstr(MI);
+ Builder.buildExtract(
+ MI.getOperand(0).getReg(),
+ MergeI->getOperand(MergeSrcIdx + 1).getReg(),
+ Offset - MergeSrcIdx * MergeSrcSize);
+ markInstAndDefDead(MI, *MergeI, DeadInsts);
+ return true;
+ }
+
/// Try to combine away MI.
/// Returns true if it combined away the MI.
/// Adds instructions that are dead as a result of the combine
@@ -223,6 +329,8 @@
return tryCombineSExt(MI, DeadInsts);
case TargetOpcode::G_UNMERGE_VALUES:
return tryCombineMerges(MI, DeadInsts);
+ case TargetOpcode::G_EXTRACT:
+ return tryCombineExtract(MI, DeadInsts);
case TargetOpcode::G_TRUNC: {
bool Changed = false;
for (auto &Use : MRI.use_instructions(MI.getOperand(0).getReg()))
@@ -233,6 +341,23 @@
}
private:
+
+ static unsigned getArtifactSrcReg(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ case TargetOpcode::COPY:
+ case TargetOpcode::G_TRUNC:
+ case TargetOpcode::G_ZEXT:
+ case TargetOpcode::G_ANYEXT:
+ case TargetOpcode::G_SEXT:
+ case TargetOpcode::G_UNMERGE_VALUES:
+ return MI.getOperand(MI.getNumOperands() - 1).getReg();
+ case TargetOpcode::G_EXTRACT:
+ return MI.getOperand(1).getReg();
+ default:
+ llvm_unreachable("Not a legalization artifact happen");
+ }
+ }
+
/// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
/// dead due to MI being killed, then mark DefMI as dead too.
/// Some of the combines (extends(trunc)), try to walk through redundant
@@ -253,8 +378,8 @@
// and as a result, %3, %2, %1 are dead.
MachineInstr *PrevMI = &MI;
while (PrevMI != &DefMI) {
- unsigned PrevRegSrc =
- PrevMI->getOperand(PrevMI->getNumOperands() - 1).getReg();
+ unsigned PrevRegSrc = getArtifactSrcReg(*PrevMI);
+
MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
if (MRI.hasOneUse(PrevRegSrc)) {
if (TmpDef != &DefMI) {
@@ -277,6 +402,28 @@
auto Step = LI.getAction(Query);
return Step.Action == Unsupported || Step.Action == NotFound;
}
+
+ bool isConstantUnsupported(LLT Ty) const {
+ if (!Ty.isVector())
+ return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
+
+ LLT EltTy = Ty.getElementType();
+ return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
+ isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
+ }
+
+ /// Looks through copy instructions and returns the actual
+ /// source register.
+ unsigned lookThroughCopyInstrs(unsigned Reg) {
+ unsigned TmpReg;
+ while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) {
+ if (MRI.getType(TmpReg).isValid())
+ Reg = TmpReg;
+ else
+ break;
+ }
+ return Reg;
+ }
};
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Legalizer.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Legalizer.h
index 8284ab6..0181650 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Legalizer.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Legalizer.h
@@ -1,9 +1,8 @@
-//== llvm/CodeGen/GlobalISel/LegalizePass.h ------------- -*- C++ -*-==//
+//== llvm/CodeGen/GlobalISel/Legalizer.h ---------------- -*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 4d804d0..136356c 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -1,9 +1,8 @@
//== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -32,6 +31,7 @@
class LegalizerInfo;
class Legalizer;
class MachineRegisterInfo;
+class GISelChangeObserver;
class LegalizerHelper {
public:
@@ -48,8 +48,10 @@
UnableToLegalize,
};
- LegalizerHelper(MachineFunction &MF);
- LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI);
+ LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer,
+ MachineIRBuilder &B);
+ LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
+ GISelChangeObserver &Observer, MachineIRBuilder &B);
/// Replace \p MI by a sequence of legal instructions that can implement the
/// same operation. Note that this means \p MI may be deleted, so any iterator
@@ -84,11 +86,11 @@
/// Legalize a vector instruction by increasing the number of vector elements
/// involved and ignoring the added elements later.
LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
- LLT WideTy);
+ LLT MoreTy);
/// Expose MIRBuilder so clients can set their own RecordInsertInstruction
/// functions
- MachineIRBuilder MIRBuilder;
+ MachineIRBuilder &MIRBuilder;
/// Expose LegalizerInfo so the clients can re-use.
const LegalizerInfo &getLegalizerInfo() const { return LI; }
@@ -102,21 +104,102 @@
unsigned ExtOpcode);
/// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
+ /// Use by truncating the operand's type to \p NarrowTy using G_TRUNC, and
+ /// replacing the vreg of the operand in place.
+ void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx);
+
+ /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
/// Def by extending the operand's type to \p WideTy and truncating it back
/// with the \p TruncOpcode, and replacing the vreg of the operand in place.
void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0,
unsigned TruncOpcode = TargetOpcode::G_TRUNC);
+ // Legalize a single operand \p OpIdx of the machine instruction \p MI as a
+ // Def by truncating the operand's type to \p NarrowTy, replacing in place and
+ // extending back with \p ExtOpcode.
+ void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx,
+ unsigned ExtOpcode);
+ /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
+ /// Def by performing it with additional vector elements and extracting the
+ /// result elements, and replacing the vreg of the operand in place.
+ void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx);
+
+ LegalizeResult
+ widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
+ LegalizeResult
+ widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
+ LegalizeResult
+ widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
+ LegalizeResult
+ widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
+
/// Helper function to split a wide generic register into bitwise blocks with
/// the given Type (which implies the number of blocks needed). The generic
/// registers created are appended to Ops, starting at bit 0 of Reg.
void extractParts(unsigned Reg, LLT Ty, int NumParts,
SmallVectorImpl<unsigned> &VRegs);
+ /// Version which handles irregular splits.
+ bool extractParts(unsigned Reg, LLT RegTy, LLT MainTy,
+ LLT &LeftoverTy,
+ SmallVectorImpl<unsigned> &VRegs,
+ SmallVectorImpl<unsigned> &LeftoverVRegs);
+
+ /// Helper function to build a wide generic register \p DstReg of type \p
+ /// RegTy from smaller parts. This will produce a G_MERGE_VALUES,
+ /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate
+ /// for the types.
+ ///
+ /// \p PartRegs must be registers of type \p PartTy.
+ ///
+ /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the
+ /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy.
+ void insertParts(unsigned DstReg, LLT ResultTy,
+ LLT PartTy, ArrayRef<unsigned> PartRegs,
+ LLT LeftoverTy = LLT(), ArrayRef<unsigned> LeftoverRegs = {});
+
+ LegalizeResult fewerElementsVectorImplicitDef(MachineInstr &MI,
+ unsigned TypeIdx, LLT NarrowTy);
+
+ /// Legalize a simple vector instruction where all operands are the same type
+ /// by splitting into multiple components.
+ LegalizeResult fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
+ LLT NarrowTy);
+
+ /// Legalize a instruction with a vector type where each operand may have a
+ /// different element type. All type indexes must have the same number of
+ /// elements.
+ LegalizeResult fewerElementsVectorMultiEltType(MachineInstr &MI,
+ unsigned TypeIdx, LLT NarrowTy);
+
+ LegalizeResult fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
+ LLT NarrowTy);
+
+ LegalizeResult
+ fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy);
+
+ LegalizeResult
+ fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy);
+
+ LegalizeResult
+ reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy);
+
+ LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
+ LLT HalfTy, LLT ShiftAmtTy);
+
+ LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
+ LegalizeResult narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
+ LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
+ LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
+
+ LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
+
LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
MachineRegisterInfo &MRI;
const LegalizerInfo &LI;
+ /// To keep track of changes made by the LegalizerHelper.
+ GISelChangeObserver &Observer;
};
/// Helper function that creates the given libcall.
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index a8c2608..5979173 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -39,6 +38,7 @@
class MachineIRBuilder;
class MachineRegisterInfo;
class MCInstrInfo;
+class GISelChangeObserver;
namespace LegalizeActions {
enum LegalizeAction : std::uint8_t {
@@ -121,7 +121,7 @@
ArrayRef<LLT> Types;
struct MemDesc {
- uint64_t Size;
+ uint64_t SizeInBits;
AtomicOrdering Ordering;
};
@@ -204,15 +204,40 @@
std::initializer_list<TypePairAndMemSize> TypesAndMemSizeInit);
/// True iff the specified type index is a scalar.
LegalityPredicate isScalar(unsigned TypeIdx);
+/// True iff the specified type index is a vector.
+LegalityPredicate isVector(unsigned TypeIdx);
+/// True iff the specified type index is a pointer (with any address space).
+LegalityPredicate isPointer(unsigned TypeIdx);
+/// True iff the specified type index is a pointer with the specified address
+/// space.
+LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace);
+
/// True iff the specified type index is a scalar that's narrower than the given
/// size.
LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size);
+
/// True iff the specified type index is a scalar that's wider than the given
/// size.
LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size);
+
+/// True iff the specified type index is a scalar or vector with an element type
+/// that's narrower than the given size.
+LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size);
+
+/// True iff the specified type index is a scalar or a vector with an element
+/// type that's wider than the given size.
+LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size);
+
/// True iff the specified type index is a scalar whose size is not a power of
/// 2.
LegalityPredicate sizeNotPow2(unsigned TypeIdx);
+
+/// True iff the specified type index is a scalar or vector whose element size
+/// is not a power of 2.
+LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx);
+
+/// True iff the specified type indices are both the same bit size.
+LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1);
/// True iff the specified MMO index has a size that is not a power of 2
LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
/// True iff the specified type index is a vector whose element count is not a
@@ -227,13 +252,25 @@
namespace LegalizeMutations {
/// Select this specific type for the given type index.
LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
+
/// Keep the same type as the given type index.
LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx);
-/// Widen the type for the given type index to the next power of 2.
-LegalizeMutation widenScalarToNextPow2(unsigned TypeIdx, unsigned Min = 0);
+
+/// Keep the same scalar or element type as the given type index.
+LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx);
+
+/// Keep the same scalar or element type as the given type.
+LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty);
+
+/// Widen the scalar type or vector element type for the given type index to the
+/// next power of 2.
+LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0);
+
/// Add more elements to the type for the given type index to the next power of
/// 2.
LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
+/// Break up the vector type for the given type index into the element type.
+LegalizeMutation scalarize(unsigned TypeIdx);
} // end namespace LegalizeMutations
/// A single rule in a legalizer info ruleset.
@@ -596,13 +633,29 @@
return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
}
+ /// Unconditionally custom lower.
+ LegalizeRuleSet &custom() {
+ return customIf(always);
+ }
+
/// Widen the scalar to the next power of two that is at least MinSize.
/// No effect if the type is not a scalar or is a power of two.
LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx,
unsigned MinSize = 0) {
using namespace LegalityPredicates;
- return actionIf(LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
- LegalizeMutations::widenScalarToNextPow2(TypeIdx, MinSize));
+ return actionIf(
+ LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
+ LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
+ }
+
+ /// Widen the scalar or vector element type to the next power of two that is
+ /// at least MinSize. No effect if the scalar size is a power of two.
+ LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx,
+ unsigned MinSize = 0) {
+ using namespace LegalityPredicates;
+ return actionIf(
+ LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)),
+ LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
}
LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
@@ -611,6 +664,21 @@
Mutation);
}
+ LegalizeRuleSet &scalarize(unsigned TypeIdx) {
+ using namespace LegalityPredicates;
+ return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)),
+ LegalizeMutations::scalarize(TypeIdx));
+ }
+
+ /// Ensure the scalar is at least as wide as Ty.
+ LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT &Ty) {
+ using namespace LegalityPredicates;
+ using namespace LegalizeMutations;
+ return actionIf(LegalizeAction::WidenScalar,
+ scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
+ changeElementTo(typeIdx(TypeIdx), Ty));
+ }
+
/// Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) {
using namespace LegalityPredicates;
@@ -621,6 +689,15 @@
}
/// Ensure the scalar is at most as wide as Ty.
+ LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT &Ty) {
+ using namespace LegalityPredicates;
+ using namespace LegalizeMutations;
+ return actionIf(LegalizeAction::NarrowScalar,
+ scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
+ changeElementTo(typeIdx(TypeIdx), Ty));
+ }
+
+ /// Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) {
using namespace LegalityPredicates;
using namespace LegalizeMutations;
@@ -636,12 +713,12 @@
const LLT &Ty) {
using namespace LegalityPredicates;
using namespace LegalizeMutations;
- return actionIf(LegalizeAction::NarrowScalar,
- [=](const LegalityQuery &Query) {
- return widerThan(TypeIdx, Ty.getSizeInBits()) &&
- Predicate(Query);
- },
- changeTo(typeIdx(TypeIdx), Ty));
+ return actionIf(
+ LegalizeAction::NarrowScalar,
+ [=](const LegalityQuery &Query) {
+ return widerThan(TypeIdx, Ty.getSizeInBits()) && Predicate(Query);
+ },
+ changeElementTo(typeIdx(TypeIdx), Ty));
}
/// Limit the range of scalar sizes to MinTy and MaxTy.
@@ -651,6 +728,27 @@
return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
}
+ /// Limit the range of scalar sizes to MinTy and MaxTy.
+ LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT &MinTy,
+ const LLT &MaxTy) {
+ return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy);
+ }
+
+ /// Widen the scalar to match the size of another.
+ LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) {
+ typeIdx(TypeIdx);
+ return widenScalarIf(
+ [=](const LegalityQuery &Query) {
+ return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
+ Query.Types[TypeIdx].getSizeInBits();
+ },
+ [=](const LegalityQuery &Query) {
+ LLT T = Query.Types[LargeTypeIdx];
+ return std::make_pair(TypeIdx,
+ T.isVector() ? T.getElementType() : T);
+ });
+ }
+
/// Add more elements to the vector to reach the next power of two.
/// No effect if the type is not a vector or the element count is a power of
/// two.
@@ -676,7 +774,7 @@
[=](const LegalityQuery &Query) {
LLT VecTy = Query.Types[TypeIdx];
return std::make_pair(
- TypeIdx, LLT::vector(MinElements, VecTy.getScalarSizeInBits()));
+ TypeIdx, LLT::vector(MinElements, VecTy.getElementType()));
});
}
/// Limit the number of elements in EltTy vectors to at most MaxElements.
@@ -693,8 +791,8 @@
},
[=](const LegalityQuery &Query) {
LLT VecTy = Query.Types[TypeIdx];
- return std::make_pair(
- TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits()));
+ LLT NewTy = LLT::scalarOrVector(MaxElements, VecTy.getElementType());
+ return std::make_pair(TypeIdx, NewTy);
});
}
/// Limit the number of elements for the given vectors to at least MinTy's
@@ -947,9 +1045,9 @@
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
- virtual bool legalizeCustom(MachineInstr &MI,
- MachineRegisterInfo &MRI,
- MachineIRBuilder &MIRBuilder) const;
+ virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
+ MachineIRBuilder &MIRBuilder,
+ GISelChangeObserver &Observer) const;
private:
/// Determine what action should be taken to legalize the given generic
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Localizer.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Localizer.h
index 1e2d476..cfc7c35 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Localizer.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Localizer.h
@@ -1,9 +1,8 @@
//== llvm/CodeGen/GlobalISel/Localizer.h - Localizer -------------*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
index f77f9a8..1f4ee8a 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
@@ -1,9 +1,8 @@
//== ----- llvm/CodeGen/GlobalISel/MIPatternMatch.h --------------------- == //
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index a837cf0..6e1ff7c 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.h - MIBuilder --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
@@ -14,6 +13,7 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
#define LLVM_CODEGEN_GLOBALISEL_MACHINEIRBUILDER_H
+#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
#include "llvm/CodeGen/GlobalISel/Types.h"
#include "llvm/CodeGen/LowLevelType.h"
@@ -30,6 +30,7 @@
class MachineFunction;
class MachineInstr;
class TargetInstrInfo;
+class GISelChangeObserver;
/// Class which stores all the state required in a MachineIRBuilder.
/// Since MachineIRBuilders will only store state in this object, it allows
@@ -50,57 +51,175 @@
MachineBasicBlock::iterator II;
/// @}
- std::function<void(MachineInstr *)> InsertedInstr;
+ GISelChangeObserver *Observer;
+
+ GISelCSEInfo *CSEInfo;
};
+class DstOp {
+ union {
+ LLT LLTTy;
+ unsigned Reg;
+ const TargetRegisterClass *RC;
+ };
+
+public:
+ enum class DstType { Ty_LLT, Ty_Reg, Ty_RC };
+ DstOp(unsigned R) : Reg(R), Ty(DstType::Ty_Reg) {}
+ DstOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(DstType::Ty_Reg) {}
+ DstOp(const LLT &T) : LLTTy(T), Ty(DstType::Ty_LLT) {}
+ DstOp(const TargetRegisterClass *TRC) : RC(TRC), Ty(DstType::Ty_RC) {}
+
+ void addDefToMIB(MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) const {
+ switch (Ty) {
+ case DstType::Ty_Reg:
+ MIB.addDef(Reg);
+ break;
+ case DstType::Ty_LLT:
+ MIB.addDef(MRI.createGenericVirtualRegister(LLTTy));
+ break;
+ case DstType::Ty_RC:
+ MIB.addDef(MRI.createVirtualRegister(RC));
+ break;
+ }
+ }
+
+ LLT getLLTTy(const MachineRegisterInfo &MRI) const {
+ switch (Ty) {
+ case DstType::Ty_RC:
+ return LLT{};
+ case DstType::Ty_LLT:
+ return LLTTy;
+ case DstType::Ty_Reg:
+ return MRI.getType(Reg);
+ }
+ llvm_unreachable("Unrecognised DstOp::DstType enum");
+ }
+
+ unsigned getReg() const {
+ assert(Ty == DstType::Ty_Reg && "Not a register");
+ return Reg;
+ }
+
+ const TargetRegisterClass *getRegClass() const {
+ switch (Ty) {
+ case DstType::Ty_RC:
+ return RC;
+ default:
+ llvm_unreachable("Not a RC Operand");
+ }
+ }
+
+ DstType getDstOpKind() const { return Ty; }
+
+private:
+ DstType Ty;
+};
+
+class SrcOp {
+ union {
+ MachineInstrBuilder SrcMIB;
+ unsigned Reg;
+ CmpInst::Predicate Pred;
+ };
+
+public:
+ enum class SrcType { Ty_Reg, Ty_MIB, Ty_Predicate };
+ SrcOp(unsigned R) : Reg(R), Ty(SrcType::Ty_Reg) {}
+ SrcOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(SrcType::Ty_Reg) {}
+ SrcOp(const MachineInstrBuilder &MIB) : SrcMIB(MIB), Ty(SrcType::Ty_MIB) {}
+ SrcOp(const CmpInst::Predicate P) : Pred(P), Ty(SrcType::Ty_Predicate) {}
+
+ void addSrcToMIB(MachineInstrBuilder &MIB) const {
+ switch (Ty) {
+ case SrcType::Ty_Predicate:
+ MIB.addPredicate(Pred);
+ break;
+ case SrcType::Ty_Reg:
+ MIB.addUse(Reg);
+ break;
+ case SrcType::Ty_MIB:
+ MIB.addUse(SrcMIB->getOperand(0).getReg());
+ break;
+ }
+ }
+
+ LLT getLLTTy(const MachineRegisterInfo &MRI) const {
+ switch (Ty) {
+ case SrcType::Ty_Predicate:
+ llvm_unreachable("Not a register operand");
+ case SrcType::Ty_Reg:
+ return MRI.getType(Reg);
+ case SrcType::Ty_MIB:
+ return MRI.getType(SrcMIB->getOperand(0).getReg());
+ }
+ llvm_unreachable("Unrecognised SrcOp::SrcType enum");
+ }
+
+ unsigned getReg() const {
+ switch (Ty) {
+ case SrcType::Ty_Predicate:
+ llvm_unreachable("Not a register operand");
+ case SrcType::Ty_Reg:
+ return Reg;
+ case SrcType::Ty_MIB:
+ return SrcMIB->getOperand(0).getReg();
+ }
+ llvm_unreachable("Unrecognised SrcOp::SrcType enum");
+ }
+
+ CmpInst::Predicate getPredicate() const {
+ switch (Ty) {
+ case SrcType::Ty_Predicate:
+ return Pred;
+ default:
+ llvm_unreachable("Not a register operand");
+ }
+ }
+
+ SrcType getSrcOpKind() const { return Ty; }
+
+private:
+ SrcType Ty;
+};
+
+class FlagsOp {
+ Optional<unsigned> Flags;
+
+public:
+ explicit FlagsOp(unsigned F) : Flags(F) {}
+ FlagsOp() : Flags(None) {}
+ Optional<unsigned> getFlags() const { return Flags; }
+};
/// Helper class to build MachineInstr.
/// It keeps internally the insertion point and debug location for all
/// the new instructions we want to create.
/// This information can be modify via the related setters.
-class MachineIRBuilderBase {
+class MachineIRBuilder {
MachineIRBuilderState State;
- void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
protected:
- unsigned getDestFromArg(unsigned Reg) { return Reg; }
- unsigned getDestFromArg(LLT Ty) {
- return getMF().getRegInfo().createGenericVirtualRegister(Ty);
- }
- unsigned getDestFromArg(const TargetRegisterClass *RC) {
- return getMF().getRegInfo().createVirtualRegister(RC);
- }
+ void validateTruncExt(const LLT &Dst, const LLT &Src, bool IsExtend);
- void addUseFromArg(MachineInstrBuilder &MIB, unsigned Reg) {
- MIB.addUse(Reg);
- }
+ void validateBinaryOp(const LLT &Res, const LLT &Op0, const LLT &Op1);
+ void validateShiftOp(const LLT &Res, const LLT &Op0, const LLT &Op1);
- void addUseFromArg(MachineInstrBuilder &MIB, const MachineInstrBuilder &UseMIB) {
- MIB.addUse(UseMIB->getOperand(0).getReg());
- }
-
- void addUsesFromArgs(MachineInstrBuilder &MIB) { }
- template<typename UseArgTy, typename ... UseArgsTy>
- void addUsesFromArgs(MachineInstrBuilder &MIB, UseArgTy &&Arg1, UseArgsTy &&... Args) {
- addUseFromArg(MIB, Arg1);
- addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
- }
- unsigned getRegFromArg(unsigned Reg) { return Reg; }
- unsigned getRegFromArg(const MachineInstrBuilder &MIB) {
- return MIB->getOperand(0).getReg();
- }
-
- void validateBinaryOp(unsigned Res, unsigned Op0, unsigned Op1);
+ void validateSelectOp(const LLT &ResTy, const LLT &TstTy, const LLT &Op0Ty,
+ const LLT &Op1Ty);
+ void recordInsertion(MachineInstr *MI) const;
public:
/// Some constructors for easy use.
- MachineIRBuilderBase() = default;
- MachineIRBuilderBase(MachineFunction &MF) { setMF(MF); }
- MachineIRBuilderBase(MachineInstr &MI) : MachineIRBuilderBase(*MI.getMF()) {
+ MachineIRBuilder() = default;
+ MachineIRBuilder(MachineFunction &MF) { setMF(MF); }
+ MachineIRBuilder(MachineInstr &MI) : MachineIRBuilder(*MI.getMF()) {
setInstr(MI);
}
- MachineIRBuilderBase(const MachineIRBuilderState &BState) : State(BState) {}
+ virtual ~MachineIRBuilder() = default;
+
+ MachineIRBuilder(const MachineIRBuilderState &BState) : State(BState) {}
const TargetInstrInfo &getTII() {
assert(State.TII && "TargetInstrInfo is not set");
@@ -113,21 +232,35 @@
return *State.MF;
}
+ const MachineFunction &getMF() const {
+ assert(State.MF && "MachineFunction is not set");
+ return *State.MF;
+ }
+
/// Getter for DebugLoc
const DebugLoc &getDL() { return State.DL; }
/// Getter for MRI
MachineRegisterInfo *getMRI() { return State.MRI; }
+ const MachineRegisterInfo *getMRI() const { return State.MRI; }
/// Getter for the State
MachineIRBuilderState &getState() { return State; }
/// Getter for the basic block we currently build.
- MachineBasicBlock &getMBB() {
+ const MachineBasicBlock &getMBB() const {
assert(State.MBB && "MachineBasicBlock is not set");
return *State.MBB;
}
+ MachineBasicBlock &getMBB() {
+ return const_cast<MachineBasicBlock &>(
+ const_cast<const MachineIRBuilder *>(this)->getMBB());
+ }
+
+ GISelCSEInfo *getCSEInfo() { return State.CSEInfo; }
+ const GISelCSEInfo *getCSEInfo() const { return State.CSEInfo; }
+
/// Current insertion point for new instructions.
MachineBasicBlock::iterator getInsertPt() { return State.II; }
@@ -137,10 +270,12 @@
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II);
/// @}
+ void setCSEInfo(GISelCSEInfo *Info);
+
/// \name Setters for the insertion point.
/// @{
/// Set the MachineFunction where to build instructions.
- void setMF(MachineFunction &);
+ void setMF(MachineFunction &MF);
/// Set the insertion point to the end of \p MBB.
/// \pre \p MBB must be contained by getMF().
@@ -151,12 +286,8 @@
void setInstr(MachineInstr &MI);
/// @}
- /// \name Control where instructions we create are recorded (typically for
- /// visiting again later during legalization).
- /// @{
- void recordInsertion(MachineInstr *InsertedInstr) const;
- void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr);
- void stopRecordingInsertions();
+ void setChangeObserver(GISelChangeObserver &Observer);
+ void stopObservingChanges();
/// @}
/// Set the debug location to \p DL for all the next build instructions.
@@ -300,9 +431,9 @@
/// registers with the same scalar type (typically s1)
///
/// \return The newly created instruction.
- MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
- unsigned Op1, unsigned CarryIn);
-
+ MachineInstrBuilder buildUAdde(const DstOp &Res, const DstOp &CarryOut,
+ const SrcOp &Op0, const SrcOp &Op1,
+ const SrcOp &CarryIn);
/// Build and insert \p Res = G_ANYEXT \p Op0
///
@@ -318,11 +449,7 @@
///
/// \return The newly created instruction.
- MachineInstrBuilder buildAnyExt(unsigned Res, unsigned Op);
- template <typename DstType, typename ArgType>
- MachineInstrBuilder buildAnyExt(DstType &&Res, ArgType &&Arg) {
- return buildAnyExt(getDestFromArg(Res), getRegFromArg(Arg));
- }
+ MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op);
/// Build and insert \p Res = G_SEXT \p Op
///
@@ -336,11 +463,16 @@
/// \pre \p Op must be smaller than \p Res
///
/// \return The newly created instruction.
- template <typename DstType, typename ArgType>
- MachineInstrBuilder buildSExt(DstType &&Res, ArgType &&Arg) {
- return buildSExt(getDestFromArg(Res), getRegFromArg(Arg));
- }
- MachineInstrBuilder buildSExt(unsigned Res, unsigned Op);
+ MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op);
+
+ /// \return The opcode of the extension the target wants to use for boolean
+ /// values.
+ unsigned getBoolExtOp(bool IsVec, bool IsFP) const;
+
+ // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_SEXT \p Op, or \p Res
+ // = G_ZEXT \p Op depending on how the target wants to extend boolean values.
+ MachineInstrBuilder buildBoolExt(const DstOp &Res, const SrcOp &Op,
+ bool IsFP);
/// Build and insert \p Res = G_ZEXT \p Op
///
@@ -354,11 +486,7 @@
/// \pre \p Op must be smaller than \p Res
///
/// \return The newly created instruction.
- template <typename DstType, typename ArgType>
- MachineInstrBuilder buildZExt(DstType &&Res, ArgType &&Arg) {
- return buildZExt(getDestFromArg(Res), getRegFromArg(Arg));
- }
- MachineInstrBuilder buildZExt(unsigned Res, unsigned Op);
+ MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op);
/// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
@@ -368,11 +496,7 @@
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
- template <typename DstTy, typename UseArgTy>
- MachineInstrBuilder buildSExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) {
- return buildSExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use));
- }
- MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op);
+ MachineInstrBuilder buildSExtOrTrunc(const DstOp &Res, const SrcOp &Op);
/// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
@@ -382,11 +506,7 @@
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
- template <typename DstTy, typename UseArgTy>
- MachineInstrBuilder buildZExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) {
- return buildZExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use));
- }
- MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op);
+ MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op);
// Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
@@ -396,11 +516,7 @@
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
- template <typename DstTy, typename UseArgTy>
- MachineInstrBuilder buildAnyExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) {
- return buildAnyExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use));
- }
- MachineInstrBuilder buildAnyExtOrTrunc(unsigned Res, unsigned Op);
+ MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op);
/// Build and insert \p Res = \p ExtOpc, \p Res = G_TRUNC \p
/// Op, or \p Res = COPY \p Op depending on the differing sizes of \p Res and
@@ -411,15 +527,11 @@
/// \pre \p Op must be a generic virtual register with scalar or vector type.
///
/// \return The newly created instruction.
- MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, unsigned Res,
- unsigned Op);
+ MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, const DstOp &Res,
+ const SrcOp &Op);
/// Build and insert an appropriate cast between two registers of equal size.
- template <typename DstType, typename ArgType>
- MachineInstrBuilder buildCast(DstType &&Res, ArgType &&Arg) {
- return buildCast(getDestFromArg(Res), getRegFromArg(Arg));
- }
- MachineInstrBuilder buildCast(unsigned Dst, unsigned Src);
+ MachineInstrBuilder buildCast(const DstOp &Dst, const SrcOp &Src);
/// Build and insert G_BR \p Dest
///
@@ -464,7 +576,8 @@
/// type.
///
/// \return The newly created instruction.
- MachineInstrBuilder buildConstant(unsigned Res, const ConstantInt &Val);
+ virtual MachineInstrBuilder buildConstant(const DstOp &Res,
+ const ConstantInt &Val);
/// Build and insert \p Res = G_CONSTANT \p Val
///
@@ -474,12 +587,9 @@
/// \pre \p Res must be a generic virtual register with scalar type.
///
/// \return The newly created instruction.
- MachineInstrBuilder buildConstant(unsigned Res, int64_t Val);
+ MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val);
+ MachineInstrBuilder buildConstant(const DstOp &Res, const APInt &Val);
- template <typename DstType>
- MachineInstrBuilder buildConstant(DstType &&Res, int64_t Val) {
- return buildConstant(getDestFromArg(Res), Val);
- }
/// Build and insert \p Res = G_FCONSTANT \p Val
///
/// G_FCONSTANT is a floating-point constant with the specified size and
@@ -489,17 +599,10 @@
/// \pre \p Res must be a generic virtual register with scalar type.
///
/// \return The newly created instruction.
- template <typename DstType>
- MachineInstrBuilder buildFConstant(DstType &&Res, const ConstantFP &Val) {
- return buildFConstant(getDestFromArg(Res), Val);
- }
- MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val);
+ virtual MachineInstrBuilder buildFConstant(const DstOp &Res,
+ const ConstantFP &Val);
- template <typename DstType>
- MachineInstrBuilder buildFConstant(DstType &&Res, double Val) {
- return buildFConstant(getDestFromArg(Res), Val);
- }
- MachineInstrBuilder buildFConstant(unsigned Res, double Val);
+ MachineInstrBuilder buildFConstant(const DstOp &Res, double Val);
/// Build and insert \p Res = COPY Op
///
@@ -508,11 +611,7 @@
/// \pre setBasicBlock or setMI must have been called.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildCopy(unsigned Res, unsigned Op);
- template <typename DstType, typename SrcType>
- MachineInstrBuilder buildCopy(DstType &&Res, SrcType &&Src) {
- return buildCopy(getDestFromArg(Res), getRegFromArg(Src));
- }
+ MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op);
/// Build and insert `Res = G_LOAD Addr, MMO`.
///
@@ -559,10 +658,7 @@
MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index);
/// Build and insert \p Res = IMPLICIT_DEF.
- template <typename DstType> MachineInstrBuilder buildUndef(DstType &&Res) {
- return buildUndef(getDestFromArg(Res));
- }
- MachineInstrBuilder buildUndef(unsigned Res);
+ MachineInstrBuilder buildUndef(const DstOp &Res);
/// Build and insert instructions to put \p Ops together at the specified p
/// Indices to form a larger register.
@@ -591,7 +687,7 @@
/// \pre The type of all \p Ops registers must be identical.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildMerge(unsigned Res, ArrayRef<unsigned> Ops);
+ MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef<unsigned> Ops);
/// Build and insert \p Res0, ... = G_UNMERGE_VALUES \p Op
///
@@ -603,7 +699,55 @@
/// \pre The type of all \p Res registers must be identical.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, unsigned Op);
+ MachineInstrBuilder buildUnmerge(ArrayRef<LLT> Res, const SrcOp &Op);
+ MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, const SrcOp &Op);
+
+ /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ...
+ ///
+ /// G_BUILD_VECTOR creates a vector value from multiple scalar registers.
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The entire register \p Res (and no more) must be covered by the
+ /// input scalar registers.
+ /// \pre The type of all \p Ops registers must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildBuildVector(const DstOp &Res,
+ ArrayRef<unsigned> Ops);
+
+ /// Build and insert \p Res = G_BUILD_VECTOR with \p Src replicated to fill
+ /// the number of elements
+ MachineInstrBuilder buildSplatVector(const DstOp &Res,
+ const SrcOp &Src);
+
+ /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ...
+ ///
+ /// G_BUILD_VECTOR_TRUNC creates a vector value from multiple scalar registers
+ /// which have types larger than the destination vector element type, and
+ /// truncates the values to fit.
+ ///
+ /// If the operands given are already the same size as the vector elt type,
+ /// then this method will instead create a G_BUILD_VECTOR instruction.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The type of all \p Ops registers must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res,
+ ArrayRef<unsigned> Ops);
+
+ /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ...
+ ///
+ /// G_CONCAT_VECTORS creates a vector from the concatenation of 2 or more
+ /// vectors.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The entire register \p Res (and no more) must be covered by the input
+ /// registers.
+ /// \pre The type of all source operands must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildConcatVectors(const DstOp &Res,
+ ArrayRef<unsigned> Ops);
MachineInstrBuilder buildInsert(unsigned Res, unsigned Src,
unsigned Op, unsigned Index);
@@ -631,11 +775,7 @@
/// \pre \p Res must be smaller than \p Op
///
/// \return The newly created instruction.
- template <typename DstType, typename SrcType>
- MachineInstrBuilder buildFPTrunc(DstType &&Res, SrcType &&Src) {
- return buildFPTrunc(getDestFromArg(Res), getRegFromArg(Src));
- }
- MachineInstrBuilder buildFPTrunc(unsigned Res, unsigned Op);
+ MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op);
/// Build and insert \p Res = G_TRUNC \p Op
///
@@ -648,11 +788,7 @@
/// \pre \p Res must be smaller than \p Op
///
/// \return The newly created instruction.
- MachineInstrBuilder buildTrunc(unsigned Res, unsigned Op);
- template <typename DstType, typename SrcType>
- MachineInstrBuilder buildTrunc(DstType &&Res, SrcType &&Src) {
- return buildTrunc(getDestFromArg(Res), getRegFromArg(Src));
- }
+ MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op);
/// Build and insert a \p Res = G_ICMP \p Pred, \p Op0, \p Op1
///
@@ -666,13 +802,8 @@
/// \pre \p Pred must be an integer predicate.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildICmp(CmpInst::Predicate Pred,
- unsigned Res, unsigned Op0, unsigned Op1);
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, DstTy &&Dst,
- UseArgsTy &&... UseArgs) {
- return buildICmp(Pred, getDestFromArg(Dst), getRegFromArg(UseArgs)...);
- }
+ MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res,
+ const SrcOp &Op0, const SrcOp &Op1);
/// Build and insert a \p Res = G_FCMP \p Pred\p Op0, \p Op1
///
@@ -686,8 +817,8 @@
/// \pre \p Pred must be a floating-point predicate.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred,
- unsigned Res, unsigned Op0, unsigned Op1);
+ MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, const DstOp &Res,
+ const SrcOp &Op0, const SrcOp &Op1);
/// Build and insert a \p Res = G_SELECT \p Tst, \p Op0, \p Op1
///
@@ -699,12 +830,8 @@
/// elements as the other parameters.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst,
- unsigned Op0, unsigned Op1);
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildSelect(DstTy &&Dst, UseArgsTy &&... UseArgs) {
- return buildSelect(getDestFromArg(Dst), getRegFromArg(UseArgs)...);
- }
+ MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst,
+ const SrcOp &Op0, const SrcOp &Op1);
/// Build and insert \p Res = G_INSERT_VECTOR_ELT \p Val,
/// \p Elt, \p Idx
@@ -716,8 +843,10 @@
/// with scalar type.
///
/// \return The newly created instruction.
- MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val,
- unsigned Elt, unsigned Idx);
+ MachineInstrBuilder buildInsertVectorElement(const DstOp &Res,
+ const SrcOp &Val,
+ const SrcOp &Elt,
+ const SrcOp &Idx);
/// Build and insert \p Res = G_EXTRACT_VECTOR_ELT \p Val, \p Idx
///
@@ -727,8 +856,9 @@
/// \pre \p Idx must be a generic virtual register with scalar type.
///
/// \return The newly created instruction.
- MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val,
- unsigned Idx);
+ MachineInstrBuilder buildExtractVectorElement(const DstOp &Res,
+ const SrcOp &Val,
+ const SrcOp &Idx);
/// Build and insert `OldValRes<def>, SuccessRes<def> =
/// G_ATOMIC_CMPXCHG_WITH_SUCCESS Addr, CmpVal, NewVal, MMO`.
@@ -965,19 +1095,7 @@
///
/// \return The newly created instruction.
MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA);
-};
-/// A CRTP class that contains methods for building instructions that can
-/// be constant folded. MachineIRBuilders that want to inherit from this will
-/// need to implement buildBinaryOp (for constant folding binary ops).
-/// Alternatively, they can implement buildInstr(Opc, Dst, Uses...) to perform
-/// additional folding for Opc.
-template <typename Base>
-class FoldableInstructionsBuilder : public MachineIRBuilderBase {
- Base &base() { return static_cast<Base &>(*this); }
-
-public:
- using MachineIRBuilderBase::MachineIRBuilderBase;
/// Build and insert \p Res = G_ADD \p Op0, \p Op1
///
/// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
@@ -989,13 +1107,10 @@
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildAdd(unsigned Dst, unsigned Src0, unsigned Src1) {
- return base().buildBinaryOp(TargetOpcode::G_ADD, Dst, Src0, Src1);
- }
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
- unsigned Res = base().getDestFromArg(Ty);
- return base().buildAdd(Res, (base().getRegFromArg(UseArgs))...);
+ MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_ADD, {Dst}, {Src0, Src1}, Flags);
}
/// Build and insert \p Res = G_SUB \p Op0, \p Op1
@@ -1009,13 +1124,10 @@
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildSub(unsigned Dst, unsigned Src0, unsigned Src1) {
- return base().buildBinaryOp(TargetOpcode::G_SUB, Dst, Src0, Src1);
- }
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildSub(DstTy &&Ty, UseArgsTy &&... UseArgs) {
- unsigned Res = base().getDestFromArg(Ty);
- return base().buildSub(Res, (base().getRegFromArg(UseArgs))...);
+ MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_SUB, {Dst}, {Src0, Src1}, Flags);
}
/// Build and insert \p Res = G_MUL \p Op0, \p Op1
@@ -1028,13 +1140,40 @@
/// with the same (scalar or vector) type).
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildMul(unsigned Dst, unsigned Src0, unsigned Src1) {
- return base().buildBinaryOp(TargetOpcode::G_MUL, Dst, Src0, Src1);
+ MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_MUL, {Dst}, {Src0, Src1}, Flags);
}
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildMul(DstTy &&Ty, UseArgsTy &&... UseArgs) {
- unsigned Res = base().getDestFromArg(Ty);
- return base().buildMul(Res, (base().getRegFromArg(UseArgs))...);
+
+ MachineInstrBuilder buildUMulH(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_UMULH, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder buildSMulH(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_SMULH, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_SHL, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_LSHR, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder buildAShr(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1,
+ Optional<unsigned> Flags = None) {
+ return buildInstr(TargetOpcode::G_ASHR, {Dst}, {Src0, Src1}, Flags);
}
/// Build and insert \p Res = G_AND \p Op0, \p Op1
@@ -1048,13 +1187,9 @@
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildAnd(unsigned Dst, unsigned Src0, unsigned Src1) {
- return base().buildBinaryOp(TargetOpcode::G_AND, Dst, Src0, Src1);
- }
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildAnd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
- unsigned Res = base().getDestFromArg(Ty);
- return base().buildAnd(Res, (base().getRegFromArg(UseArgs))...);
+ MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1) {
+ return buildInstr(TargetOpcode::G_AND, {Dst}, {Src0, Src1});
}
/// Build and insert \p Res = G_OR \p Op0, \p Op1
@@ -1067,39 +1202,14 @@
/// with the same (scalar or vector) type).
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildOr(unsigned Dst, unsigned Src0, unsigned Src1) {
- return base().buildBinaryOp(TargetOpcode::G_OR, Dst, Src0, Src1);
+ MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0,
+ const SrcOp &Src1) {
+ return buildInstr(TargetOpcode::G_OR, {Dst}, {Src0, Src1});
}
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildOr(DstTy &&Ty, UseArgsTy &&... UseArgs) {
- unsigned Res = base().getDestFromArg(Ty);
- return base().buildOr(Res, (base().getRegFromArg(UseArgs))...);
- }
-};
-class MachineIRBuilder : public FoldableInstructionsBuilder<MachineIRBuilder> {
-public:
- using FoldableInstructionsBuilder<
- MachineIRBuilder>::FoldableInstructionsBuilder;
- MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst,
- unsigned Src0, unsigned Src1) {
- validateBinaryOp(Dst, Src0, Src1);
- return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1);
- }
- using FoldableInstructionsBuilder<MachineIRBuilder>::buildInstr;
- /// DAG like Generic method for building arbitrary instructions as above.
- /// \Opc opcode for the instruction.
- /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
- /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
- /// Uses of type MachineInstrBuilder will perform
- /// getOperand(0).getReg() to convert to register.
- template <typename DstTy, typename... UseArgsTy>
- MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
- UseArgsTy &&... Args) {
- auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
- addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...);
- return MIB;
- }
+ virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
+ ArrayRef<SrcOp> SrcOps,
+ Optional<unsigned> Flags = None);
};
} // End namespace llvm.
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
index c53ae41..c31ca5c 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
@@ -1,9 +1,8 @@
//=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBank.h
index d5612e1..f528d1a 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBank.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBank.h
@@ -1,9 +1,8 @@
//==-- llvm/CodeGen/GlobalISel/RegisterBank.h - Register Bank ----*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
index 82fd7ed..37a63d1 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ---------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -103,8 +102,8 @@
/// Currently the TableGen-like file would look like:
/// \code
/// PartialMapping[] = {
- /// /*32-bit add*/ {0, 32, GPR},
- /// /*2x32-bit add*/ {0, 32, GPR}, {0, 32, GPR}, // <-- Same entry 3x
+ /// /*32-bit add*/ {0, 32, GPR}, // Scalar entry repeated for first vec elt.
+ /// /*2x32-bit add*/ {0, 32, GPR}, {32, 32, GPR},
/// /*<2x32-bit> vadd {0, 64, VPR}
/// }; // PartialMapping duplicated.
///
@@ -118,14 +117,15 @@
/// With the array of pointer, we would have:
/// \code
/// PartialMapping[] = {
- /// /*32-bit add*/ {0, 32, GPR},
+ /// /*32-bit add lower */ {0, 32, GPR},
+ /// /*32-bit add upper */ {32, 32, GPR},
/// /*<2x32-bit> vadd {0, 64, VPR}
/// }; // No more duplication.
///
/// BreakDowns[] = {
/// /*AddBreakDown*/ &PartialMapping[0],
- /// /*2xAddBreakDown*/ &PartialMapping[0], &PartialMapping[0],
- /// /*VAddBreakDown*/ &PartialMapping[1]
+ /// /*2xAddBreakDown*/ &PartialMapping[0], &PartialMapping[1],
+ /// /*VAddBreakDown*/ &PartialMapping[2]
/// }; // Addresses of PartialMapping duplicated (smaller).
///
/// ValueMapping[] {
@@ -160,6 +160,10 @@
const PartialMapping *begin() const { return BreakDown; }
const PartialMapping *end() const { return BreakDown + NumBreakDowns; }
+ /// \return true if all partial mappings are the same size and register
+ /// bank.
+ bool partsAllUniform() const;
+
/// Check if this ValueMapping is valid.
bool isValid() const { return BreakDown && NumBreakDowns; }
@@ -617,6 +621,15 @@
return &A != &B;
}
+ /// Get the cost of using \p ValMapping to decompose a register. This is
+ /// similar to ::copyCost, except for cases where multiple copy-like
+ /// operations need to be inserted. If the register is used as a source
+ /// operand and already has a bank assigned, \p CurBank is non-null.
+ virtual unsigned getBreakDownCost(const ValueMapping &ValMapping,
+ const RegisterBank *CurBank = nullptr) const {
+ return std::numeric_limits<unsigned>::max();
+ }
+
/// Constrain the (possibly generic) virtual register \p Reg to \p RC.
///
/// \pre \p Reg is a virtual register that either has a bank or a class.
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Types.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Types.h
index 7b22e34..4fd7043 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Types.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Types.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
///
diff --git a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Utils.h b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Utils.h
index 51e3a27..dd14a0c 100644
--- a/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/linux-x64/clang/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -1,9 +1,8 @@
//==-- llvm/CodeGen/GlobalISel/Utils.h ---------------------------*- C++ -*-==//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
//
@@ -108,5 +107,8 @@
/// fallback.
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU);
+Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1,
+ const unsigned Op2,
+ const MachineRegisterInfo &MRI);
} // End namespace llvm.
#endif