[PATCH] SROA produces miscompiled code for bitfield access on big-endian targets

Alexandros Lamprineas alexandros.lamprineas at arm.com
Wed Jun 10 06:16:15 PDT 2015


Hi chandlerc,

{F556279}

The attached code is miscompiled when targeting big-endian at all optimisation levels except for -O0. This should print "checksum = 00000008", but actually prints "checksum = 00000000". It is correctly compiled if I change the statement just before the function call to func_13 from l_15.f0 to l_15.f1 (the result of this expression is unused). The only change this causes in the IR is to change the parameter in the call to func_13 from 0x800000180 to 0x800018000.

The problem seems to be in the 'scalar replacement of aggregates' pass. The problem arises because we have a 7-byte type but the alloca is 8 bytes (because it's 4-byte aligned), which causes the aggregate to be split up into two 4-byte slices except one actually ends up being 3 bytes. The pass takes into account endianness, thus adds a shift instruction when inserting an integer to an alloca store:
  if(DL.isBigEndian())
    ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - DL.getTypeStoreSize(Ty) - Offset);
In this particular example an integer value of wrong size ({i32}) is passed as parameter to the function that computes the shift amount (‘insertInteger’). This causes a zero shift amount since IntTy = {i64}, Ty = {i32}, and offset = 4 bytes. My patch passes a parameter of Ty = {i24} to ‘insertInteger’.

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D10357

Files:
  lib/Transforms/Scalar/SROA.cpp
  test/Transforms/SROA/big-endian.ll

Index: test/Transforms/SROA/big-endian.ll
===================================================================
--- test/Transforms/SROA/big-endian.ll
+++ test/Transforms/SROA/big-endian.ll
@@ -112,3 +112,35 @@
 ; CHECK-NEXT: %[[ret:.*]] = zext i56 %[[insert4]] to i64
 ; CHECK-NEXT: ret i64 %[[ret]]
 }
+
+%struct.S0 = type { i32, i24 }
+
+ at main.l_15 = private unnamed_addr constant { i32, i8, i8, i8 } { i32 8, i8 0, i8 1, i8 -128 }, align 4
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)
+
+define i64 @test3() {
+; CHECK-LABEL: @test3(
+entry:
+  %l_15 = alloca %struct.S0, align 4
+  %r0 = bitcast %struct.S0* %l_15 to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %r0, i8* bitcast ({ i32, i8, i8, i8 }* @main.l_15 to i8*), i64 8, i32 4, i1 false)
+  %f0 = getelementptr inbounds %struct.S0, %struct.S0* %l_15, i32 0, i32 0
+  %r1 = load i32, i32* %f0, align 4
+  %r2 = bitcast %struct.S0* %l_15 to i64*
+  %r3 = load i64, i64* %r2, align 1
+  ret i64 %r3
+; CHECK:      %[[ld_f0:.*]] = load i32, i32* getelementptr inbounds ({ i32, i8, i8, i8 }, { i32, i8, i8, i8 }* @main.l_15, i64 0, i32 0), align 4
+; CHECK-NEXT: %[[ld_f1:.*]] = load i24, i24* bitcast (i8* getelementptr inbounds ({ i32, i8, i8, i8 }, { i32, i8, i8, i8 }* @main.l_15, i64 0, i32 1) to i24*), align 4
+; CHECK-NEXT: %[[ld:.*]] = load i8, i8* getelementptr inbounds (i8, i8* bitcast ({ i32, i8, i8, i8 }* @main.l_15 to i8*), i64 7), align 1
+; CHECK-NEXT: %[[ext:.*]] = zext i24 %[[ld_f1]] to i64
+; CHECK-NEXT: %[[shift:.*]] = shl i64 %[[ext]], 8
+; CHECK-NEXT: %[[mask:.*]] = and i64 undef, -4294967041
+; CHECK-NEXT: %[[insert:.*]] = or i64 %[[mask]], %[[shift]]
+; CHECK-NEXT: %[[ext1:.*]] = zext i32 %[[ld_f0]] to i64
+; CHECK-NEXT: %[[shift1:.*]] = shl i64 %[[ext1]], 32
+; CHECK-NEXT: %[[mask1:.*]] = and i64 %[[insert]], 4294967295
+; CHECK-NEXT: %[[insert1:.*]] = or i64 %[[mask1]], %[[shift1]]
+; CHECK-NEXT: ret i64 %[[insert1]]
+}
+
Index: lib/Transforms/Scalar/SROA.cpp
===================================================================
--- lib/Transforms/Scalar/SROA.cpp
+++ lib/Transforms/Scalar/SROA.cpp
@@ -2583,8 +2583,9 @@
     Value *OldOp = LI.getOperand(0);
     assert(OldOp == OldPtr);
 
-    Type *TargetTy = IsSplit ? Type::getIntNTy(LI.getContext(), SliceSize * 8)
-                             : LI.getType();
+    Type *TargetTy = IsSplit ? 
+                     Type::getIntNTy(LI.getContext(),DL.getTypeStoreSizeInBits(NewAllocaTy)) 
+                   : LI.getType();
     bool IsPtrAdjusted = false;
     Value *V;
     if (VecTy) {

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D10357.27436.patch
Type: text/x-patch
Size: 2564 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150610/d865f40b/attachment.bin>


More information about the llvm-commits mailing list