[LLVMdev] MIScheduler + AA: Missed scheduling opportunity in MIsNeedChainEdge. Bug?

Ziqiang Patrick Huang zh28 at duke.edu
Wed Jul 1 13:38:42 PDT 2015


I noticed this too and I'm not sure why isUnsafeMemoryObject
<http://llvm.org/docs/doxygen/html/ScheduleDAGInstrs_8cpp.html#a25fe0578f0a0e48d63fcf4ab7a892dd5>
returns
true for such simple array access. But before reaching that check, you
should hit

   // Let the target decide if memory accesses cannot possibly
overlap.00527   if ((MIa->mayLoad
<http://llvm.org/docs/doxygen/html/classllvm_1_1MachineInstr.html#a2b48451e9cc8433ed5f8ee30462cc96e>()
|| MIa->mayStore
<http://llvm.org/docs/doxygen/html/classllvm_1_1MachineInstr.html#aa5f0eb2aad4a731d5d5133b8cb5e0a98>())
&&00528       (MIb->mayLoad
<http://llvm.org/docs/doxygen/html/classllvm_1_1MachineInstr.html#a2b48451e9cc8433ed5f8ee30462cc96e>()
|| MIb->mayStore
<http://llvm.org/docs/doxygen/html/classllvm_1_1MachineInstr.html#aa5f0eb2aad4a731d5d5133b8cb5e0a98>()))00529
    if (TII->areMemAccessesTriviallyDisjoint
<http://llvm.org/docs/doxygen/html/classllvm_1_1TargetInstrInfo.html#a255c4fa466c5f2ba7e52f67296834de8>(MIa,
MIb, AA))00530       return false;


Here your target could override areMemAcdessesTriviallyDisjoint() function
to make it work, at least for the example you gave.

Patrick

2015-07-01 15:08 GMT-04:00 Johnson, Nicholas Paul <
Nicholas.Paul.Johnson at deshawresearch.com>:

> Hello,
>
> While tuning the MIScheduler for my target, I discovered a code that
> unnecessarily restricts the scheduler.  I think this is a bug, but I would
> appreciate a second opinion.
>
>
> In file ScheduleDAGInstrs.cpp, the function MIsNeedChainEdge determines
> whether two MachineInstrs are ordered by a memory dependence.  It first
> runs through the standard criteria (Do both instructions access memory?
> Does at least one store to memory?  Is either access volatile?  etc.), and
> finally queries AliasAnalysis if available.
>
> Before reaching alias analysis, however, function isUnsafeMemoryObject
> pessimizes the result.  In particular, isUnsafeMemoryObject returns true
> unless all of the pointer's underlying objects satisfy IsIdentifiedObject.
> This forces MIsNeedChainEdge to conservatively report true, even though
> AliasAnalysis could give a more precise answer in some situations.
> Further, it is unclear why this test even exists: it does not attempt to
> compare the underlying object sets to test for an alias, and the volatility
> check should cover all this-object-is-not-quite-memory situations.
>
> As a simple example of why this matters, suppose that you have a function
> like this:
>   void doit(int *baseptr) {
>     baseptr[0] = 1; // store 1
>     baseptr[1] = 2; // store 2
>   }
>
> In this example, stores 1 and 2 can be freely re-ordered.  However,
> isUnsafeMemoryObject reports true because the underlying objects (formal
> parameter 'baseptr') do not satisfy IsIdentifiedObject.  Nonetheless,
> BasicAliasAnalysis can show that derived pointers &baseptr[0] and
> &baseptr[1] are disjoint.
>
>
> Proposed solution:
> - If MIsNeedChainEdge is invoked without alias analysis (AA=nullptr),
> behavior should be unchanged.
> - Otherwise, isUnsafeMemoryObject should not test for identified objects.
> - A minimal patch appears at the end of this email.
>
>
> Thanks,
> Nick Johnson
> D. E. Shaw Research
>
>
>
> diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp
> b/lib/CodeGen/ScheduleDAGInstrs.cpp
> index 390b6d2..fcf43ca 100644
> --- a/lib/CodeGen/ScheduleDAGInstrs.cpp
> +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
> @@ -475,7 +475,8 @@ static inline bool isGlobalMemoryObject(AliasAnalysis
> *AA, MachineInstr *MI) {
>  // to deal with (i.e. volatile object).
>  static inline bool isUnsafeMemoryObject(MachineInstr *MI,
>                                          const MachineFrameInfo *MFI,
> -                                        const DataLayout &DL) {
> +                                        const DataLayout &DL,
> +                                        AliasAnalysis *AA) {
>    if (!MI || MI->memoperands_empty())
>      return true;
>    // We purposefully do no check for hasOneMemOperand() here
> @@ -497,6 +498,7 @@ static inline bool isUnsafeMemoryObject(MachineInstr
> *MI,
>    if (!V)
>      return true;
>
> +  if (!AA) {
>      SmallVector<Value *, 4> Objs;
>      getUnderlyingObjects(V, Objs, DL);
>      for (Value *V : Objs) {
> @@ -504,6 +506,7 @@ static inline bool isUnsafeMemoryObject(MachineInstr
> *MI,
>        if (!isIdentifiedObject(V))
>          return true;
>      }
> +  }
>
>    return false;
>  }
> @@ -533,7 +536,7 @@ static bool MIsNeedChainEdge(AliasAnalysis *AA, const
> MachineFrameInfo *MFI,
>    if (!MIa->hasOneMemOperand() || !MIb->hasOneMemOperand())
>      return true;
>
> -  if (isUnsafeMemoryObject(MIa, MFI, DL) || isUnsafeMemoryObject(MIb,
> MFI, DL))
> +  if (isUnsafeMemoryObject(MIa, MFI, DL, AA) || isUnsafeMemoryObject(MIb,
> MFI, DL, AA))
>      return true;
>
>    // If we are dealing with two "normal" loads, we do not need an edge
>
>
>
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150701/b78b4293/attachment.html>


More information about the llvm-dev mailing list