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.
On Thu, Mar 1, 2012 at 1:04 PM, Sergei Larin <slarin at codeaurora.org> wrote:> 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?Err, are you sure you're asking the right question? Given the loads you're pointing at, you're asking whether &s and &q alias. -Eli
> Err, are you sure you're asking the right question? Given the loads > you're pointing at, you're asking whether &s and &q alias.Yes. And I am pretty sure this enquiry works fine for 99.9999% of cases, but has some issue with this one... Scheduling is notorious for exposing latent bugs way later after they have been introduced :( Sergei -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum.> -----Original Message----- > From: Eli Friedman [mailto:eli.friedman at gmail.com] > Sent: Thursday, March 01, 2012 3:15 PM > To: Sergei Larin > Cc: llvmdev at cs.uiuc.edu > Subject: Re: [LLVMdev] Aliasing bug or feature? > > On Thu, Mar 1, 2012 at 1:04 PM, Sergei Larin <slarin at codeaurora.org> > wrote: > > 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? > > Err, are you sure you're asking the right question? Given the loads > you're pointing at, you're asking whether &s and &q alias. > > -Eli
On Thu, Mar 1, 2012 at 2:00 PM, Sergei Larin <slarin at codeaurora.org> wrote:> Eli, > > I might not have answered your question fully/accurately... > > On my architecture, these _two_ loads are lowered to a single instruction: > > %3 = load i8** @q, align 4, !tbaa !2 > %4 = load i8* %3, align 1, !tbaa !0 > > Becomes > > i32,ch = LDw_GP_V4 0x3df4c70, 0x3df5470<Mem:LD4[@q](tbaa=!"any pointer") > > I guess what is happening, the alias properties of combined instruction are > not updated properly, and I am not sure if this is something I need to do, > or it is getting done "automatically" somewhere at DAG combine... Sorry. > Still learning :)Ah, that explains it: you've only attached one memory operand to an instruction that reads from two memory locations. You probably just need to add the second memory operand. -Eli