[llvm-dev] [buildSchedGraph] memory dependencies

Hal Finkel via llvm-dev llvm-dev at lists.llvm.org
Wed Feb 3 17:51:06 PST 2016


----- Original Message -----
> From: "Jonas Paulsson via llvm-dev" <llvm-dev at lists.llvm.org>
> To: "llvm-dev" <llvm-dev at lists.llvm.org>
> Sent: Wednesday, February 3, 2016 4:41:33 AM
> Subject: [llvm-dev] [buildSchedGraph] memory dependencies
> 
> Hi,
> 
> (This only concerns MISNeedChainEdge(), and is separate from D8705)
> 
> I found out that the MIScheduler (pre-ra) could not handle a simple
> test
> case (test/CodeGen/SystemZ/alias-01.ll), with 16 independent load /
> add
> / stores.
> 
> The buildSchedGraph() put too many edges between memory accesses,
> because
> 1) There was no implementation of areMemAccessesTriviallyDisjoint()
> for
> SystemZ.
> 2) Type Based Alias Analysis (TBAA) was not used.
> 
> I have gotten rid of the edges on an experimental level, and would
> now
> like some help and feedback:
> 
> 1): It seems common for targets to check for the same virtual address
> register and then figure out via offsets/sizes if they overlap. When
> faced with the task of doing this, I realized that the
> MachineMemOperands might do the job. I tried the following and wonder
> why this is not done already, perhaps as a default implementation of
> areMemAccessesTriviallyDisjoint(). Is it because memory operands may
> be
> missing, or is it because MachineCombiner may give the register based
> analysis an advantage? This is a check in the case of the *same
> Value*.
> In this case the Value is an argument, which is unsafe against
> others,
> but I am thinking it should at least be safe against itself...
> 
> diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp
> b/lib/CodeGen/ScheduleDAGInstrs.cpp
> index 00a0b0f..cd48f51 100644
> --- a/lib/CodeGen/ScheduleDAGInstrs.cpp
> +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
> @@ -584,6 +584,25 @@ static bool MIsNeedChainEdge(AliasAnalysis *AA,
> const MachineFrameInfo *MFI,
>     if (!MIa->hasOneMemOperand() || !MIb->hasOneMemOperand())
>       return true;
> 
> +  // If mem-operands show that the same address Value is used by
> both
> +  // ("normal") instructions, simply check offsets and sizes of the
> +  // accesses.
> +  MachineMemOperand *MMOa = *MIa->memoperands_begin();
> +  MachineMemOperand *MMOb = *MIb->memoperands_begin();
> +  const Value *VALa = MMOa->getValue();
> +  const Value *VALb = MMOb->getValue();
> +  if (VALa == VALb &&
> +      !MIa->hasUnmodeledSideEffects() &&
> !MIb->hasUnmodeledSideEffects() &&
> +      !MIa->hasOrderedMemoryRef() && !MIb->hasOrderedMemoryRef()) {
> +    int OffsetA = MMOa->getOffset(), OffsetB = MMOb->getOffset();
> +    int WidthA = MMOa->getSize(), WidthB = MMOb->getSize();
> +    int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
> +    int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
> +    int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
> +    if (LowOffset + LowWidth <= HighOffset)
> +      return false;
> +  }
> +
>     if (isUnsafeMemoryObject(MIa, MFI, DL) ||
>     isUnsafeMemoryObject(MIb,
> MFI, DL))
>       return true;
> 

This looks reasonable to me.

> 
> 2) The TBAA tags should separate the loads from the stores. In the MF
> I see
> ...
> %vreg32<def> = L %vreg0, 56, %noreg;
> mem:LD4[%src1(align=64)+56](align=8)(tbaa=!1) GR32Bit:%vreg32
> ADDR64Bit:%vreg0
> ...
> ST %vreg33, %vreg1, 60, %noreg;
> mem:ST4[%dest(align=64)+60](align=4)(tbaa=!4) GR32Bit:%vreg33
> ADDR64Bit:%vreg1
> ...
> 
> Since the tbba tags are part of the MachineMemOperands, it is easy to
> just continue the patch (above isUnsafeMemoryObject() checks) with
> 
> +  AAMDNodes AATagsA = MMOa->getAAInfo(), AATagsB =
> MMOb->getAAInfo();
> +  if (AATagsA->TBAA && AATagsB->TBAA && AATagsA != AATagsB)
> +    return false;
> 
> I see that there is a TBAA method that is intended to give this type
> of
> result. So I wonder why this is not used?
> 
> Would it be correct to implement SystemZs
> areMemAccessesTriviallyDisjoint() with the above code? (I am
> suspecting
> that perhaps my AAMDNodes check is incomplete)

I don't understand this. The whole point of allowing backends use AA is to let the existing AA infrastructure take care of this. As I recall, SystemZ enabled AA in the backend, so why do you need anything special here?

 -Hal

> 
> /Jonas
> 
> test case:
> 
> define void @f1(<16 x i32> *%src1, <16 x float> *%dest) {
> ; CHECK-LABEL: f1:
> ; CHECK-NOT: %r15
> ; CHECK: br %r14
>    %val = load <16 x i32> , <16 x i32> *%src1, !tbaa !1
>    %add = add <16 x i32> %val, %val
>    %res = bitcast <16 x i32> %add to <16 x float>
>    store <16 x float> %res, <16 x float> *%dest, !tbaa !2
>    ret void
> }
> 
> !0 = !{ !"root" }
> !1 = !{ !"set1", !0 }
> !2 = !{ !"set2", !0 }
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory


More information about the llvm-dev mailing list