I am running into a problem when I turn on post-RA scheduler with mode “ANTIDEP_CRITICAL” for mips.
I’d appreciate if someone could explain what is going wrong here.
This is the basic block before post RA scheduling (at PostRASchedulerList.cpp:322):
(gdb)
#3 0x0000000000ed3d26 in runOnMachineFunction (this=0x20aa470, Fn=…)
at lib/CodeGen/PostRASchedulerList.cpp:322
322 Scheduler.Observe(MI, CurrentCount);
(gdb) p (*MBB).dump()
BB#218: derived from LLVM BB %if.then1289
Live Ins: %A2 %S0_64 %S1_64 %S2_64 %S4 %S5_64 %T0 %T1 %T2 %T3_64 %T6 %T8 %T9
Predecessors according to CFG: BB#217
…
%V0 = ADDu %ZERO, %T9
%T9_64 = LD_P8 %T3_64, ga:intrapred[TF=3]; mem:LD8[GOT]
…
JALR64 %T9_64, %A0_64, %A1, %A2, %A3, %T0, , %SP, %V0
…
BNE %V0, %V1, <BB#372>
MI is JALR64 which is a call (jump-and-link-register). T9_64 is the destination register and A0 - A3 and T0 are the argument registers.
These registers are not callee-saved.
(gdb) p MI->dump()
JALR64 %T9_64, %A0_64, %A1, %A2, %A3, %T0, , %SP, %V0
After the region above the JALR64 instruction is scheduled, the basic block looks like this (at PostRASchedulerList.cpp:341):
(gdb)
341 Scheduler.FixupKills(MBB);
(gdb) p (*MBB).dump()
BB#218: derived from LLVM BB %if.then1289
Live Ins: %A2 %S0_64 %S1_64 %S2_64 %S4 %S5_64 %T0 %T1 %T2 %T3_64 %T6 %T8 %T9
Predecessors according to CFG: BB#217
%S6_64 = LD_P8 %T3_64, ga:intrapred[TF=3]; mem:LD8[GOT]
%V0 = ADDu %ZERO, %T9
…
JALR64 %S6_64, %A0_64, %A1, %A2, %A3, %T0, , %SP, %V0
…
$110 = void
CriticalAntiDepBreaker has replaced T9_64 with S6_64 to break an anti-dependence edge.
This code is incorrect since the first operand of JALR64 has to be T9_64 in PIC mode.
After further investigation, I found that the flag for T9_64 of CriticalAntiDepBreaker::KeepRegs that had been set in PrescanInstruction was reset in ScanInstruction, which I think is causing the problem:
CriticalAntiDepBreaker.cpp:
00154 PrescanInstruction(MI);
00155 ScanInstruction(MI, Count);
T9_64 is cleared in CriticalAntiDepBreaker.cpp:264:
Breakpoint 8, llvm::CriticalAntiDepBreaker::ScanInstruction (this=0x262d290,
MI=0x22b2168, Count=15)
at lib/CodeGen/CriticalAntiDepBreaker.cpp:264
264 KeepRegs.reset(i);
(gdb) p i
$179 = 145
(gdb) p /x KeepRegs.test(145)
$180 = 0x1
145 is the value of T9_64.
In CriticalAntiDepBreaker.cpp, there is a comment " Also assume all registers used in a call must not be changed (ABI).", but T9_64 is changed here. Also it says “registers that are defed but not used in this instruction are now dead”, but I don’t see the code that checks whether T9_64 is used.