assert(!MRI.getType(Reg).isPointer() &&
"Pointers are gprb, they should not be considered as ambiguous.\n");
for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
- if (UseMI.getOpcode() == TargetOpcode::COPY &&
- !TargetRegisterInfo::isPhysicalRegister(UseMI.getOperand(0).getReg()))
- // Copies of non-physical registers are not supported
- return;
-
- DefUses.push_back(&UseMI);
+ MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
+ // Copy with many uses.
+ if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
+ !TargetRegisterInfo::isPhysicalRegister(
+ NonCopyInstr->getOperand(0).getReg()))
+ addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
+ else
+ DefUses.push_back(skipCopiesOutgoing(&UseMI));
}
}
assert(!MRI.getType(Reg).isPointer() &&
"Pointers are gprb, they should not be considered as ambiguous.\n");
MachineInstr *DefMI = MRI.getVRegDef(Reg);
- if (DefMI->getOpcode() == TargetOpcode::COPY &&
- !TargetRegisterInfo::isPhysicalRegister(DefMI->getOperand(1).getReg()))
- // Copies from non-physical registers are not supported.
- return;
+ UseDefs.push_back(skipCopiesIncoming(DefMI));
+}
+
+MachineInstr *
+MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
+ MachineInstr *MI) const {
+ const MachineFunction &MF = *MI->getParent()->getParent();
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
+ MachineInstr *Ret = MI;
+ while (Ret->getOpcode() == TargetOpcode::COPY &&
+ !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
+ MRI.hasOneUse(Ret->getOperand(0).getReg())) {
+ Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
+ }
+ return Ret;
+}
- UseDefs.push_back(DefMI);
+MachineInstr *
+MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
+ MachineInstr *MI) const {
+ const MachineFunction &MF = *MI->getParent()->getParent();
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
+ MachineInstr *Ret = MI;
+ while (Ret->getOpcode() == TargetOpcode::COPY &&
+ !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(1).getReg()))
+ Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
+ return Ret;
}
MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
void addDefUses(Register Reg, const MachineRegisterInfo &MRI);
void addUseDef(Register Reg, const MachineRegisterInfo &MRI);
+ /// Skip copy instructions until we get to a non-copy instruction or to a
+ /// copy with phys register as def. Used during search for DefUses.
+ /// MI : %5 = COPY %4
+ /// %6 = COPY %5
+ /// $v0 = COPY %6 <- we want this one.
+ MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const;
+
+ /// Skip copy instructions until we get to a non-copy instruction or to a
+ /// copy with phys register as use. Used during search for UseDefs.
+ /// %1 = COPY $a1 <- we want this one.
+ /// %2 = COPY %1
+ /// MI = %3 = COPY %2
+ MachineInstr *skipCopiesIncoming(MachineInstr *MI) const;
+
public:
AmbiguousRegDefUseContainer(const MachineInstr *MI);
SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; }
--- /dev/null
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+
+ define void @skipCopiesOutgoing(float* %ptr_a, float* %ptr_b, float* %ptr_c) {entry: ret void}
+ define void @skipCopiesIncoming(float* %float_ptr) {entry: ret void}
+
+...
+---
+name: skipCopiesOutgoing
+alignment: 2
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a0, $a1, $a2
+
+ ; MIPS32-LABEL: name: skipCopiesOutgoing
+ ; MIPS32: liveins: $a0, $a1, $a2
+ ; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
+ ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1
+ ; MIPS32: [[COPY2:%[0-9]+]]:gprb(p0) = COPY $a2
+ ; MIPS32: [[LOAD:%[0-9]+]]:fprb(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.ptr_a)
+ ; MIPS32: [[COPY3:%[0-9]+]]:fprb(s32) = COPY [[LOAD]](s32)
+ ; MIPS32: G_STORE [[COPY3]](s32), [[COPY1]](p0) :: (store 4 into %ir.ptr_b)
+ ; MIPS32: [[COPY4:%[0-9]+]]:fprb(s32) = COPY [[COPY3]](s32)
+ ; MIPS32: G_STORE [[COPY4]](s32), [[COPY2]](p0) :: (store 4 into %ir.ptr_c)
+ ; MIPS32: $f0 = COPY [[COPY4]](s32)
+ ; MIPS32: RetRA implicit $f0
+ %0:_(p0) = COPY $a0
+ %1:_(p0) = COPY $a1
+ %2:_(p0) = COPY $a2
+ %3:_(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr_a)
+ %4:_(s32) = COPY %3(s32)
+ G_STORE %4(s32), %1(p0) :: (store 4 into %ir.ptr_b)
+ %5:_(s32) = COPY %4(s32)
+ G_STORE %5(s32), %2(p0) :: (store 4 into %ir.ptr_c)
+ $f0 = COPY %5(s32)
+ RetRA implicit $f0
+
+...
+---
+name: skipCopiesIncoming
+alignment: 2
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $a2, $a3, $f12, $f14
+
+ ; MIPS32-LABEL: name: skipCopiesIncoming
+ ; MIPS32: liveins: $a2, $a3, $f12, $f14
+ ; MIPS32: [[COPY:%[0-9]+]]:fprb(s32) = COPY $f12
+ ; MIPS32: [[COPY1:%[0-9]+]]:fprb(s32) = COPY $f14
+ ; MIPS32: [[COPY2:%[0-9]+]]:gprb(p0) = COPY $a2
+ ; MIPS32: [[COPY3:%[0-9]+]]:gprb(s32) = COPY $a3
+ ; MIPS32: [[LOAD:%[0-9]+]]:fprb(s32) = G_LOAD [[COPY2]](p0) :: (load 4 from %ir.float_ptr)
+ ; MIPS32: [[FADD:%[0-9]+]]:fprb(s32) = G_FADD [[COPY1]], [[COPY]]
+ ; MIPS32: [[COPY4:%[0-9]+]]:fprb(s32) = COPY [[FADD]](s32)
+ ; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 1
+ ; MIPS32: [[COPY5:%[0-9]+]]:gprb(s32) = COPY [[COPY3]](s32)
+ ; MIPS32: [[AND:%[0-9]+]]:gprb(s32) = G_AND [[COPY5]], [[C]]
+ ; MIPS32: [[COPY6:%[0-9]+]]:fprb(s32) = COPY [[COPY4]](s32)
+ ; MIPS32: [[SELECT:%[0-9]+]]:fprb(s32) = G_SELECT [[AND]](s32), [[LOAD]], [[COPY6]]
+ ; MIPS32: $f0 = COPY [[SELECT]](s32)
+ ; MIPS32: RetRA implicit $f0
+ %0:_(s32) = COPY $f12
+ %1:_(s32) = COPY $f14
+ %2:_(p0) = COPY $a2
+ %4:_(s32) = COPY $a3
+ %5:_(s32) = G_LOAD %2(p0) :: (load 4 from %ir.float_ptr)
+ %6:_(s32) = G_FADD %1, %0
+ %11:_(s32) = COPY %6(s32)
+ %9:_(s32) = G_CONSTANT i32 1
+ %10:_(s32) = COPY %4(s32)
+ %8:_(s32) = G_AND %10, %9
+ %12:_(s32) = COPY %11(s32)
+ %7:_(s32) = G_SELECT %8(s32), %5, %12
+ $f0 = COPY %7(s32)
+ RetRA implicit $f0
+
+...