unsigned Alignment = 0;
bool ExposesReturnsTwice = false;
bool HasInlineAsm = false;
+ // MachineFunctionProperties
+ bool AllVRegsAllocated = false;
// Register information
bool IsSSA = false;
bool TracksRegLiveness = false;
YamlIO.mapOptional("alignment", MF.Alignment);
YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
+ YamlIO.mapOptional("allVRegsAllocated", MF.AllVRegsAllocated);
YamlIO.mapOptional("isSSA", MF.IsSSA);
YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H
#define LLVM_CODEGEN_MACHINEFUNCTION_H
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/ilist.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/DebugLoc.h"
}
};
+/// Properties which a MachineFunction may have at a given point in time.
+/// Each of these has checking code in the MachineVerifier, and passes can
+/// require that a property be set.
+class MachineFunctionProperties {
+ // TODO: Add MachineVerifier checks for AllVRegsAllocated
+ // TODO: Add a way to print the properties and make more useful error messages
+ // Possible TODO: Allow targets to extend this (perhaps by allowing the
+ // constructor to specify the size of the bit vector)
+ // Possible TODO: Allow requiring the negative (e.g. VRegsAllocated could be
+ // stated as the negative of "has vregs"
+
+ // Stated in "positive" form; i.e. a pass could require that the property
+ // hold, but not that it does not hold.
+ BitVector Properties =
+ BitVector(static_cast<unsigned>(Property::LastProperty));
+
+ public:
+ // Property descriptions:
+ // IsSSA (currently unused, intended to eventually replace
+ // MachineRegisterInfo::isSSA())
+ // TracksLiveness: (currently unsued, intended to eventually replace
+ // MachineRegisterInfo::tracksLiveness())
+ // AllVRegsAllocated: All virtual registers have been allocated; i.e. all
+ // register operands are physical registers.
+ enum class Property : unsigned {
+ IsSSA,
+ TracksLiveness,
+ AllVRegsAllocated,
+ LastProperty,
+ };
+
+ bool hasProperty(Property P) const {
+ return Properties[static_cast<unsigned>(P)];
+ }
+ MachineFunctionProperties &set(Property P) {
+ Properties.set(static_cast<unsigned>(P));
+ return *this;
+ }
+ MachineFunctionProperties &clear(Property P) {
+ Properties.reset(static_cast<unsigned>(P));
+ return *this;
+ }
+ MachineFunctionProperties &set(const MachineFunctionProperties &MFP) {
+ Properties |= MFP.Properties;
+ return *this;
+ }
+ MachineFunctionProperties &clear(const MachineFunctionProperties &MFP) {
+ Properties.reset(MFP.Properties);
+ return *this;
+ }
+ // Returns true if all properties set in V (i.e. required by a pass) are set
+ // in this.
+ bool verifyRequiredProperties(const MachineFunctionProperties &V) const {
+ return !V.Properties.test(Properties);
+ }
+};
+
class MachineFunction {
const Function *Fn;
const TargetMachine &Target;
/// True if the function includes any inline assembly.
bool HasInlineAsm = false;
+ /// Current high-level properties of the IR of the function (e.g. is in SSA
+ /// form or whether registers have been allocated)
+ MachineFunctionProperties Properties;
+
// Allocation management for pseudo source values.
std::unique_ptr<PseudoSourceValueManager> PSVManager;
HasInlineAsm = B;
}
+ /// Get the function properties
+ const MachineFunctionProperties &getProperties() const { return Properties; }
+ MachineFunctionProperties &getProperties() { return Properties; }
+
/// getInfo - Keep track of various per-function pieces of information for
/// backends that would like to do so.
///
#define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H
#include "llvm/Pass.h"
+#include "llvm/CodeGen/MachineFunction.h"
namespace llvm {
-class MachineFunction;
-
/// MachineFunctionPass - This class adapts the FunctionPass interface to
/// allow convenient creation of passes that operate on the MachineFunction
/// representation. Instead of overriding runOnFunction, subclasses
/// override runOnMachineFunction.
class MachineFunctionPass : public FunctionPass {
+public:
+ bool doInitialization(Module&) override {
+ // Cache the properties info at module-init time so we don't have to
+ // construct them for every function.
+ RequiredProperties = getRequiredProperties();
+ SetProperties = getSetProperties();
+ ClearedProperties = getClearedProperties();
+ return false;
+ }
protected:
explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {}
///
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ virtual MachineFunctionProperties getRequiredProperties() const {
+ return MachineFunctionProperties();
+ }
+ virtual MachineFunctionProperties getSetProperties() const {
+ return MachineFunctionProperties();
+ }
+ virtual MachineFunctionProperties getClearedProperties() const {
+ return MachineFunctionProperties();
+ }
+
private:
+ MachineFunctionProperties RequiredProperties;
+ MachineFunctionProperties SetProperties;
+ MachineFunctionProperties ClearedProperties;
+
/// createPrinterPass - Get a machine function printer pass.
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override;
}
bool runOnMachineFunction(MachineFunction &F) override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
};
}
}
bool runOnMachineFunction(MachineFunction &MF) override;
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
};
/// \brief Detect re-ordering hazards and dependencies.
/// information we preserve.
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
/// Print to ostream with a message.
void printVarLocInMBB(const VarLocInMBB &V, const char *msg,
raw_ostream &Out) const;
MF.setAlignment(YamlMF.Alignment);
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
+ if (YamlMF.AllVRegsAllocated)
+ MF.getProperties().set(MachineFunctionProperties::Property::AllVRegsAllocated);
PerFunctionMIParsingState PFS;
if (initializeRegisterInfo(MF, YamlMF, PFS))
return true;
YamlMF.Alignment = MF.getAlignment();
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
YamlMF.HasInlineAsm = MF.hasInlineAsm();
+ YamlMF.AllVRegsAllocated = MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+
convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
ModuleSlotTracker MST(MF.getFunction()->getParent());
MST.incorporateFunction(*MF.getFunction());
bool runOnMachineFunction(MachineFunction &MF) override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
private:
void ClobberRegister(unsigned Reg);
void CopyPropagateBlock(MachineBasicBlock &MBB);
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/StackProtector.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
+
using namespace llvm;
Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O,
return false;
MachineFunction &MF = getAnalysis<MachineFunctionAnalysis>().getMF();
- return runOnMachineFunction(MF);
+ MachineFunctionProperties &MFProps = MF.getProperties();
+
+ assert(MFProps.verifyRequiredProperties(RequiredProperties) &&
+ "Properties required by the pass are not met by the function");
+
+ bool RV = runOnMachineFunction(MF);
+
+ MFProps.set(SetProperties);
+ MFProps.clear(ClearedProperties);
+ return RV;
}
void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
}
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
bool runOnMachineFunction(MachineFunction &Fn) override;
bool enablePostRAScheduler(
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
/// runOnMachineFunction - Insert prolog/epilog code and replace abstract
/// frame indexes with appropriate references.
///
/// RABasic analysis usage.
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ MachineFunctionProperties getSetProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
void releaseMemory() override;
Spiller &spiller() override { return *SpillerInstance; }
static char ID;
RAFast() : MachineFunctionPass(ID), StackSlotForVirtReg(-1),
isBulkSpilling(false) {}
+
private:
MachineFunction *MF;
MachineRegisterInfo *MRI;
MachineFunctionPass::getAnalysisUsage(AU);
}
+ MachineFunctionProperties getSetProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
private:
bool runOnMachineFunction(MachineFunction &Fn) override;
void AllocateBasicBlock();
/// RAGreedy analysis usage.
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ MachineFunctionProperties getSetProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
void releaseMemory() override;
Spiller &spiller() override { return *SpillerInstance; }
void enqueue(LiveInterval *LI) override;
/// PBQP analysis usage.
void getAnalysisUsage(AnalysisUsage &au) const override;
+ MachineFunctionProperties getSetProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
/// Perform register allocation
bool runOnMachineFunction(MachineFunction &MF) override;
/// information we preserve.
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
/// \brief Calculate the liveness information for the given machine function.
bool runOnMachineFunction(MachineFunction &MF) override;
disablePass(&PrologEpilogCodeInserterID);
disablePass(&MachineCopyPropagationID);
disablePass(&TailDuplicateID);
+ disablePass(&StackMapLivenessID);
+ disablePass(&LiveDebugValuesID);
+ disablePass(&PostRASchedulerID);
+ disablePass(&FuncletLayoutID);
addPass(createNVVMReflectPass());
if (getOptLevel() != CodeGenOpt::None)
bool addILPOpts() override;
void addPreRegAlloc() override;
void addPostRegAlloc() override;
+ void addMachineLateOptimization() override;
+ bool addGCPasses() override { return false; }
void addPreEmitPass() override;
};
} // end anonymous namespace
// virtual registers. Consider removing their restrictions and re-enabling
// them.
//
+
+ // Has no asserts of its own, but was not written to handle virtual regs.
+ disablePass(&ShrinkWrapID);
// We use our own PrologEpilogInserter which is very slightly modified to
// tolerate virtual registers.
disablePass(&PrologEpilogCodeInserterID);
addPass(createWebAssemblyPEI());
}
+void WebAssemblyPassConfig::addMachineLateOptimization() {
+ disablePass(&MachineCopyPropagationID);
+ disablePass(&PostRASchedulerID);
+ TargetPassConfig::addMachineLateOptimization();
+}
+
void WebAssemblyPassConfig::addPreEmitPass() {
TargetPassConfig::addPreEmitPass();
// Eliminate multiple-entry loops.
addPass(createWebAssemblyFixIrreducibleControlFlow());
+ disablePass(&FuncletLayoutID);
+ disablePass(&StackMapLivenessID);
+ disablePass(&LiveDebugValuesID);
// Put the CFG in structured form; insert BLOCK and LOOP markers.
addPass(createWebAssemblyCFGStackify());
# CHECK: bb.0:
# CHECK-NOT: %w20 = COPY
name: copyprop1
+allVRegsAllocated: true
body: |
bb.0:
liveins: %w0, %w1
# CHECK: bb.0:
# CHECK: %w20 = COPY
name: copyprop2
+allVRegsAllocated: true
body: |
bb.0:
liveins: %w0, %w1
# CHECK: bb.0:
# CHECK-NOT: COPY
name: copyprop3
+allVRegsAllocated: true
body: |
bb.0:
liveins: %w0, %w1
# CHECK: bb.0:
# CHECK-NOT: COPY
name: copyprop4
+allVRegsAllocated: true
body: |
bb.0:
liveins: %w0, %w1
alignment: 1
exposesReturnsTwice: false
hasInlineAsm: false
+allVRegsAllocated: true
isSSA: false
tracksRegLiveness: true
tracksSubRegLiveness: false
# CHECK-NOT: COPY
# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
name: copyprop_remove_kill0
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rdi
# CHECK-NOT: COPY
# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
name: copyprop_remove_kill1
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rdi
# CHECK-NOT: COPY
# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
name: copyprop_remove_kill2
+allVRegsAllocated: true
body: |
bb.0:
%ax = COPY %di
# CHECK-NOT: COPY
# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
name: copyprop0
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rdi
# CHECK-NEXT: NOOP implicit %rax
# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
name: copyprop1
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rdi
# CHECK-NOT: %rax = COPY %rdi
# CHECK-NEXT: NOOP implicit %rax, implicit %rdi
name: copyprop2
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rdi
# CHECK-NEXT: %rbp = COPY %rax
# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
name: nocopyprop0
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rbp
# CHECK-NEXT: %rax = COPY %rbp
# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
name: nocopyprop1
+allVRegsAllocated: true
body: |
bb.0:
%rbp = COPY %rax
# CHECK-NEXT: %rax = COPY %rbp
# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
name: nocopyprop2
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rbp
# CHECK-NEXT: %rbp = COPY %rax
# CHECK-NEXT: NOOP implicit %rax, implicit %rbp
name: nocopyprop3
+allVRegsAllocated: true
body: |
bb.0:
%rbp = COPY %rax
# CHECK-NEXT: %rax = COPY %rip
# CHECK-NEXT: NOOP implicit %rax
name: nocopyprop4
+allVRegsAllocated: true
body: |
bb.0:
%rax = COPY %rip
# CHECK-NEXT: %rip = COPY %rax
# CHECK-NEXT: %rip = COPY %rax
name: nocopyprop5
+allVRegsAllocated: true
body: |
bb.0:
%rip = COPY %rax
alignment: 4
exposesReturnsTwice: false
hasInlineAsm: false
+allVRegsAllocated: true
isSSA: false
tracksRegLiveness: true
tracksSubRegLiveness: false
alignment: 4
exposesReturnsTwice: false
hasInlineAsm: false
+allVRegsAllocated: true
isSSA: false
tracksRegLiveness: true
tracksSubRegLiveness: false