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