[LLVMdev] Aliasing bug or feature?

Sergei Larin slarin at codeaurora.org
Thu Mar 1 13:04:17 PST 2012


Hello everyone, 

  I am working on some changes to the Hexagon VLIW PreRA scheduler, and as a
part of it need to test aliasing properties of two instruction.
What it boils down to is the following code:

char a[20];
char s;
char *p, *q; // p == &a[0]; q == &s;

void test()
{
  register char reg;

  s = 0;
  reg = p[0] + p[1];
  s = q[0] + reg;

  return;
}

When I ask the question whether "&s" and "&q[0]" may potentially alias, I
got negative affirmation. 
In the full test (not presented) they indeed may and do in fact alias,
resulting in incorrect VLIW schedule. 

My question - is it a feature or a bug :) 

Here is somewhat more info:

Before lowering begins:
*** IR Dump After Remove sign extends ***
define void @test() nounwind {
entry:
  store i8 0, i8* @s, align 1, !tbaa !0
  %0 = load i8** @p, align 4, !tbaa !2
  %1 = load i8* %0, align 1, !tbaa !0
  %conv = zext i8 %1 to i32
  %arrayidx1 = getelementptr inbounds i8* %0, i32 1
  %2 = load i8* %arrayidx1, align 1, !tbaa !0
  %conv2 = zext i8 %2 to i32
  %3 = load i8** @q, align 4, !tbaa !2 <<< Can this load be bypassed by the
store below?
  %4 = load i8* %3, align 1, !tbaa !0
  %conv5 = zext i8 %4 to i32
  %add = add i32 %conv2, %conv
  %add7 = add i32 %add, %conv5
  %conv8 = trunc i32 %add7 to i8
  store i8 %conv8, i8* @s, align 1, !tbaa !0 <<< Can this store bypass the
above load?
  ret void
}

At the point of enquiry I have the following (lowered) instructions:

x3df7900: i32,ch = LDw_GP_V4 0x3df4c70, 0x3df5470<Mem:LD4[@q](tbaa=!"any
pointer")> [ORD=8] [ID=6] // This is Load from q[0]
0x3df5470: ch = STb_GP_V4 0x3df5170, 0x3df4e70, 0x3d9c130<Mem:ST1[@s]>
[ID=4] // This is a store to s

Underlying Values:

@q = common global i8* null, align 4
@s = common global i8 0, align 1

The way inquiry is made is similar to DAGCombiner::isAlias()

SDNode *SDN1;
SDNode *SDN2;
MachineMemOperand *MMOa;
MachineMemOperand *MMOb;
...
    const MachineSDNode *MNb = dyn_cast<MachineSDNode>(SDN2);
    const MachineSDNode *MNa = dyn_cast<MachineSDNode>(SDN1);
...
    MMOa = !MNa->memoperands_empty() ?
                    (*MNa->memoperands_begin()) : NULL;
    MMOb = !MNb->memoperands_empty() ?
                    (*MNb->memoperands_begin()) : NULL;

    if (MMOa && MMOa->getValue() && MMOb && MMOb->getValue()) {

...
      int64_t MinOffset = std::min(MMOa->getOffset(), MMOb->getOffset());
      int64_t Overlapa = MMOa->getSize() + MMOa->getOffset() - MinOffset;
      int64_t Overlapb = MMOb->getSize() + MMOb->getOffset() - MinOffset;
      
      AliasAnalysis::AliasResult AAResult = AA->alias(
            AliasAnalysis::Location(MMOa->getValue(), Overlapa,
                                    MMOa->getTBAAInfo()),
            AliasAnalysis::Location(MMOb->getValue(), Overlapb,
                                    MMOb->getTBAAInfo()));

Quick debug of BasicAliasAnalysis::aliasCheck() points to this code:

if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
      return NoAlias;

And in llvm::isIdentifiedObject() this is true:
if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V))

Any qlues/suggestions are welcome. Thanks.

Sergei Larin

--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum.





More information about the llvm-dev mailing list