[LLVMdev] CriticalAntiDepBreaker rewrites a register operand of a call instruction

Akira Hatanaka ahatanak at gmail.com
Fri Apr 20 14:14:00 PDT 2012


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<def> = ADDu %ZERO, %T9<kill>
    %T9_64<def> = LD_P8 %T3_64, <ga:@intrapred>[TF=3]; mem:LD8[GOT]
    ...
    JALR64 %T9_64<kill>, %A0_64<kill>, %A1<kill>, %A2<kill>, %A3<kill>,
%T0<kill>, <regmask>, %SP<imp-def>, %V0<imp-def>
    ...
    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<kill>, %A0_64<kill>, %A1<kill>, %A2<kill>, %A3<kill>,
%T0<kill>, <regmask>, %SP<imp-def>, %V0<imp-def>
*

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<def> = LD_P8 %T3_64, <ga:@intrapred>[TF=3]; mem:LD8[GOT]
    %V0<def> = ADDu %ZERO, %T9<kill>
    ...
    JALR64 %S6_64<kill>, %A0_64<kill>, %A1<kill>, %A2<kill>, %A3<kill>,
%T0<kill>, <regmask>, %SP<imp-def>, %V0<imp-def>
    ...
$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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120420/a5c3aefd/attachment.html>


More information about the llvm-dev mailing list