summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Colombet <quentin.colombet@gmail.com>2019-05-08 18:30:26 +0000
committerQuentin Colombet <quentin.colombet@gmail.com>2019-05-08 18:30:26 +0000
commit157427245a1993870870629dd36eb978add90570 (patch)
treed2e2b1cd0c23e60c32543998eef2be96b5bd6331
parent9820d04dbcbaba1eeab72be2b436a95074e2a952 (diff)
downloadbcm5719-llvm-157427245a1993870870629dd36eb978add90570.tar.gz
bcm5719-llvm-157427245a1993870870629dd36eb978add90570.zip
[RegAllocFast] Scan physcial reg definitions before assigning virtual reg definitions
When assigning the definitions of an instruction we were updating the available registers while walking the definitions. Some of those definitions may be from physical registers and thus, they are not available for other definitions to take, but by the time we see that we may have already assign these registers to another virtual register. Fix that by walking through all the definitions and mark as unavailable the physical register definitions, then do the virtual register assignments. PR41790 llvm-svn: 360278
-rw-r--r--llvm/lib/CodeGen/RegAllocFast.cpp20
-rw-r--r--llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir19
2 files changed, 35 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index c11ae9cce1a..52502a4b821 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -1058,6 +1058,20 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
}
// Third scan.
+ // Mark all physreg defs as used before allocating virtreg defs.
+ for (unsigned I = 0; I != DefOpEnd; ++I) {
+ const MachineOperand &MO = MI.getOperand(I);
+ if (!MO.isReg() || !MO.isDef() || !MO.getReg() || MO.isEarlyClobber())
+ continue;
+ unsigned Reg = MO.getReg();
+
+ if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg) ||
+ !MRI->isAllocatable(Reg))
+ continue;
+ definePhysReg(MI, Reg, MO.isDead() ? regFree : regReserved);
+ }
+
+ // Fourth scan.
// Allocate defs and collect dead defs.
for (unsigned I = 0; I != DefOpEnd; ++I) {
const MachineOperand &MO = MI.getOperand(I);
@@ -1065,11 +1079,9 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
continue;
unsigned Reg = MO.getReg();
- if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
- if (!MRI->isAllocatable(Reg)) continue;
- definePhysReg(MI, Reg, MO.isDead() ? regFree : regReserved);
+ // We have already dealt with phys regs in the previous scan.
+ if (TargetRegisterInfo::isPhysicalRegister(Reg))
continue;
- }
MCPhysReg PhysReg = defineVirtReg(MI, I, Reg, CopySrcReg);
if (setPhysReg(MI, MI.getOperand(I), PhysReg)) {
VirtDead.push_back(Reg);
diff --git a/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir b/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir
new file mode 100644
index 00000000000..6cdac85f96f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir
@@ -0,0 +1,19 @@
+# RUN: llc -o - -mtriple=x86_64-- -run-pass=regallocfast %s | FileCheck %s
+# Fast regalloc used to not collect physical register definitions
+# before walking and assigning the virtual definition.
+# Therefore it was possible for a virtual definition to end up
+# using the same register as a later (in terms of operand list) physical
+# register.
+# Check this does not happen.
+#
+# PR41790
+---
+name: instruction_with_1virtreg_1physreg_defs
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-NOT: $rax = KILL implicit-def dead $rax
+ %0:gr64 = KILL implicit-def dead $rax
+ KILL killed %0
+ RET 0
+...
OpenPOWER on IntegriCloud