<div dir="ltr">I recently came across an issue that causes incorrect code gen in some cases on<br>PowerPC. Namely, when loading a different type from a pointer passed as a<br>parameter, the alignment emitted on the load will be the alignment of the<br>result type.<br>Case in point:<br>  vector unsigned int test(unsigned int *a) {<br>    return *(vector unsigned int*)a;<br>  }<br>The natural alignment of vectors on PPC is 16-bytes. The natural alignment of<br>int is 4. When clang is emitting the IR for this, it'll use the alignment of<br>the result of the cast on the load. So in this case, the alignment is unduly<br>strengthened which can produce incorrect code.<br><br>The following patch fixes the problem, but seems to be in direct contradiction<br>to the intent of the block of code it modifies.<br><br><span style="font-family:monospace,monospace">Index: lib/CodeGen/CGExpr.cpp<br>===================================================================<br>--- lib/CodeGen/CGExpr.cpp      (revision 290541)<br>+++ lib/CodeGen/CGExpr.cpp      (working copy)<br>@@ -851,8 +851,12 @@ Address CodeGenFunction::EmitPointerWithAlignment(<br>         // opaque, honor the alignment of the casted-to type.<br>         if (isa<ExplicitCastExpr>(CE) &&<br>             InnerSource != AlignmentSource::Decl) {<br>+          unsigned WeakestAlignment =<br>+            std::min(getNaturalPointeeTypeAlignment(E->getType(), Source).<br>+                       getQuantity(), Addr.getAlignment().getQuantity());<br>+<br>           Addr = Address(Addr.getPointer(),<br>-                         getNaturalPointeeTypeAlignment(E->getType(), Source));<br>+                         CharUnits::fromQuantity(WeakestAlignment));<br>         }<br> <br>         if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) &&<br><br></span>So my question is whether this patch is reasonable or is there a bug in that the<br>"InnerSource" AlignmentSource isn't correctly propagated (perhaps across the<br>alloca/store/load combo of instructions). Honestly, although I am not familiar<br>with this code, it seems reasonable that the source of the alignment information<br>on a parameter is its declaration, but presumably this is lost due to the<br>alloca/store/load.<br><br>For convenience, here's the IR clang produces for the above at noopt on PPC:<br><br><span style="font-family:monospace,monospace">define <4 x i32> @test(i32* %a) #0 {<br>entry:<br>  %a.addr = alloca i32*, align 8<br>  store i32* %a, i32** %a.addr, align 8<br>  %0 = load i32*, i32** %a.addr, align 8<br>  %1 = bitcast i32* %0 to <4 x i32>*<br>  %2 = load <4 x i32>, <4 x i32>* %1, align 16<br>  ret <4 x i32> %2<br>}<br></span><br></div>