<div dir="ltr">Hi All,<div><br></div><div>I'd like to float two changes to the llvm.memcpy / llvm.memmove intrinsics.</div><div><br></div><div><br></div><div>(1) Add an i1 <mayPerfectlyAlias> argument to the llvm.memcpy intrinsic.</div><div><br></div><div><span style="line-height:normal">When set to '1' (the auto-upgrade default), this argument would indicate that the source and destination arguments may perfectly alias (otherwise they must not alias at all - memcpy prohibits partial overlap). While the C standard says that memcpy's arguments can't alias at all, perfect aliasing works in practice, and clang currently relies on this behavior: it emits </span>llvm.memcpys<span style="line-height:normal"> for aggregate copies, despite the possibility of self-assignment.</span></div><div><br></div><div>Going forward, llvm.memcpy calls emitted for aggregate copies would have mayPerfectlyAlias set to '1'. Other uses of llvm.memcpy (including lowerings from memcpy calls) would have mapPerfectlyAlias set to '0'. </div><div><br></div><div><span style="line-height:normal">This change is motivated by poor optimization for small memcpys on targets with strict alignment requirements. When a user writes a small, unaligned memcpy</span> we may transform it into an unaligned load/store pair in instcombine (See InstCombine::SimplifyMemTransfer), which is then broken up into an unwieldy series of smaller loads and stores during legalization. I have a fix for this issue which tags the pointers for unaligned load/store pairs with noalias metadata allowing CodeGen to produce better code during legalization, but it's not safe to apply while clang is emitting memcpys with pointers that may perfectly alias. If the 'mayPerfectlyAlias' flag were introduced, I could inspect that and add the noalias tag only if mayPerfectlyAlias is '0'.<br></div><div><br></div><div>Note: We could also achieve the desired effect by adding a new intrinsic (llvm.structcpy?) with semantics that match the current llvm.memcpy ones (i.e. perfect-aliasing or non-aliasing, but no partial), and then reclaim llvm.memcpy for non-aliasing pointers only. I floated this idea with David Majnemer on IRC and he suggested that adding a flag to llvm.memcpy might be less disruptive and easier to maintain - thanks for the suggestion David!  </div><div><br></div><div><br></div><div><br></div><div>(2) Allow different source and destination alignments on both llvm.memcpy / llvm.memmove.</div><div><br></div><div>Since I'm talking about changes to llvm.memcpy anyway, a few people asked me to float this one. Having separate alignments for the source and destination pointers may allow us to generate better code when one of the pointers has a higher alignment.</div><div><br></div><div>The auto-upgrade for this would be to set both source and destination alignment to the original 'align' value.</div><div><br></div><div><br></div><div><br></div><div>Any thoughts?</div><div><br></div><div>Cheers,</div><div>Lang.</div><div><br></div></div>