summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/MachineRegisterInfo.cpp
diff options
context:
space:
mode:
authorJustin Bogner <mail@justinbogner.com>2018-01-18 02:06:56 +0000
committerJustin Bogner <mail@justinbogner.com>2018-01-18 02:06:56 +0000
commita9346e050f301dfea9e1cf50d39a4b7180091b44 (patch)
tree65abd702e3ae3d94d045681c3fc33f6586250b6a /llvm/lib/CodeGen/MachineRegisterInfo.cpp
parent3feefe001b2ec9bd0fd867284560cf99d7345b1f (diff)
downloadbcm5719-llvm-a9346e050f301dfea9e1cf50d39a4b7180091b44.tar.gz
bcm5719-llvm-a9346e050f301dfea9e1cf50d39a4b7180091b44.zip
GlobalISel: Make MachineCSE runnable in the middle of the GlobalISel
Right now, it is not possible to run MachineCSE in the middle of the GlobalISel pipeline. Being able to run generic optimizations between the core passes of GlobalISel was one of the goals of the new ISel framework. This is the first attempt to do it. The problem is that MachineCSE pass assumes all register operands have a register class, which, in GlobalISel context, won't be true until after the InstructionSelect pass. The reason for this behaviour is that before replacing one virtual register with another, MachineCSE pass (and most of the other optimization machine passes) must check if the virtual registers' constraints have a (sufficiently large) intersection, and constrain the resulting register appropriately if such intersection exists. GlobalISel extends the representation of such constraints from just a register class to a triple (low-level type, register bank, register class). This commit adds MachineRegisterInfo::constrainRegAttrs method that extends MachineRegisterInfo::constrainRegClass to such a triple. The idea is that going forward we should use: - RegisterBankInfo::constrainGenericRegister within GlobalISel's InstructionSelect pass - MachineRegisterInfo::constrainRegClass within SelectionDAG ISel - MachineRegisterInfo::constrainRegAttrs everywhere else regardless the target and instruction selector it uses. Patch by Roman Tereshin. Thanks! llvm-svn: 322805
Diffstat (limited to 'llvm/lib/CodeGen/MachineRegisterInfo.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineRegisterInfo.cpp57
1 files changed, 50 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index b82ab02a6e6..983822ba0c5 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -65,23 +65,66 @@ void MachineRegisterInfo::setRegBank(unsigned Reg,
VRegInfo[Reg].first = &RegBank;
}
-const TargetRegisterClass *
-MachineRegisterInfo::constrainRegClass(unsigned Reg,
- const TargetRegisterClass *RC,
- unsigned MinNumRegs) {
- const TargetRegisterClass *OldRC = getRegClass(Reg);
+static const TargetRegisterClass *
+constrainRegClass(MachineRegisterInfo &MRI, unsigned Reg,
+ const TargetRegisterClass *OldRC,
+ const TargetRegisterClass *RC, unsigned MinNumRegs) {
if (OldRC == RC)
return RC;
const TargetRegisterClass *NewRC =
- getTargetRegisterInfo()->getCommonSubClass(OldRC, RC);
+ MRI.getTargetRegisterInfo()->getCommonSubClass(OldRC, RC);
if (!NewRC || NewRC == OldRC)
return NewRC;
if (NewRC->getNumRegs() < MinNumRegs)
return nullptr;
- setRegClass(Reg, NewRC);
+ MRI.setRegClass(Reg, NewRC);
return NewRC;
}
+const TargetRegisterClass *
+MachineRegisterInfo::constrainRegClass(unsigned Reg,
+ const TargetRegisterClass *RC,
+ unsigned MinNumRegs) {
+ return ::constrainRegClass(*this, Reg, getRegClass(Reg), RC, MinNumRegs);
+}
+
+bool
+MachineRegisterInfo::constrainRegAttrs(unsigned Reg,
+ unsigned ConstrainingReg,
+ unsigned MinNumRegs) {
+ auto const *OldRC = getRegClassOrNull(Reg);
+ auto const *RC = getRegClassOrNull(ConstrainingReg);
+ // A virtual register at any point must have either a low-level type
+ // or a class assigned, but not both. The only exception is the internals of
+ // GlobalISel's instruction selection pass, which is allowed to temporarily
+ // introduce registers with types and classes both.
+ assert((OldRC || getType(Reg).isValid()) && "Reg has neither class nor type");
+ assert((!OldRC || !getType(Reg).isValid()) && "Reg has class and type both");
+ assert((RC || getType(ConstrainingReg).isValid()) &&
+ "ConstrainingReg has neither class nor type");
+ assert((!RC || !getType(ConstrainingReg).isValid()) &&
+ "ConstrainingReg has class and type both");
+ if (OldRC && RC)
+ return ::constrainRegClass(*this, Reg, OldRC, RC, MinNumRegs);
+ // If one of the virtual registers is generic (used in generic machine
+ // instructions, has a low-level type, doesn't have a class), and the other is
+ // concrete (used in target specific instructions, doesn't have a low-level
+ // type, has a class), we can not unify them.
+ if (OldRC || RC)
+ return false;
+ // At this point, both registers are guaranteed to have a valid low-level
+ // type, and they must agree.
+ if (getType(Reg) != getType(ConstrainingReg))
+ return false;
+ auto const *OldRB = getRegBankOrNull(Reg);
+ auto const *RB = getRegBankOrNull(ConstrainingReg);
+ if (OldRB)
+ return !RB || RB == OldRB;
+ if (RB)
+ setRegBank(Reg, *RB);
+ return true;
+}
+
bool
MachineRegisterInfo::recomputeRegClass(unsigned Reg) {
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
OpenPOWER on IntegriCloud