[cfe-dev] Automagic strengthening of alignment of pointer parameters through a cast

Nemanja Ivanovic via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 28 00:31:13 PST 2016


I recently came across an issue that causes incorrect code gen in some
cases on
PowerPC. Namely, when loading a different type from a pointer passed as a
parameter, the alignment emitted on the load will be the alignment of the
result type.
Case in point:
  vector unsigned int test(unsigned int *a) {
    return *(vector unsigned int*)a;
  }
The natural alignment of vectors on PPC is 16-bytes. The natural alignment
of
int is 4. When clang is emitting the IR for this, it'll use the alignment of
the result of the cast on the load. So in this case, the alignment is unduly
strengthened which can produce incorrect code.

The following patch fixes the problem, but seems to be in direct
contradiction
to the intent of the block of code it modifies.

Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp      (revision 290541)
+++ lib/CodeGen/CGExpr.cpp      (working copy)
@@ -851,8 +851,12 @@ Address CodeGenFunction::EmitPointerWithAlignment(
         // opaque, honor the alignment of the casted-to type.
         if (isa<ExplicitCastExpr>(CE) &&
             InnerSource != AlignmentSource::Decl) {
+          unsigned WeakestAlignment =
+            std::min(getNaturalPointeeTypeAlignment(E->getType(), Source).
+                       getQuantity(), Addr.getAlignment().getQuantity());
+
           Addr = Address(Addr.getPointer(),
-                         getNaturalPointeeTypeAlignment(E->getType(),
Source));
+                         CharUnits::fromQuantity(WeakestAlignment));
         }

         if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) &&

So my question is whether this patch is reasonable or is there a bug in
that the
"InnerSource" AlignmentSource isn't correctly propagated (perhaps across the
alloca/store/load combo of instructions). Honestly, although I am not
familiar
with this code, it seems reasonable that the source of the alignment
information
on a parameter is its declaration, but presumably this is lost due to the
alloca/store/load.

For convenience, here's the IR clang produces for the above at noopt on PPC:

define <4 x i32> @test(i32* %a) #0 {
entry:
  %a.addr = alloca i32*, align 8
  store i32* %a, i32** %a.addr, align 8
  %0 = load i32*, i32** %a.addr, align 8
  %1 = bitcast i32* %0 to <4 x i32>*
  %2 = load <4 x i32>, <4 x i32>* %1, align 16
  ret <4 x i32> %2
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20161228/ede89e67/attachment.html>


More information about the cfe-dev mailing list