<div dir="ltr">Hans, this is likely to be a bug fix we want on the release branch, but I'd like Hal to confirm that it's working for him on big-endian systems first.<br><br><div class="gmail_quote"><div dir="ltr">On Tue, Jul 21, 2015 at 8:35 PM Chandler Carruth <<a href="mailto:chandlerc@gmail.com">chandlerc@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chandlerc<br>
Date: Tue Jul 21 22:32:42 2015<br>
New Revision: 242869<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D242869-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=F1q3VZl0uUG9VIJ7OQ6PWCf2vaejhfp4-rFx45ltBWs&s=KBZeRj-5F9Vpb4flrdD9XX26sDCx5RCNg7xfnX0OJVY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=242869&view=rev</a><br>
Log:<br>
[SROA] Fix a nasty pile of bugs to do with big-endian, different alloca<br>
types and loads, loads or stores widened past the size of an alloca,<br>
etc.<br>
<br>
This started off with a bug report about big-endian behavior with<br>
bitfields and loads and stores to a { i32, i24 } struct. An initial<br>
attempt to fix this was sent for review in D10357, but that didn't<br>
really get to the root of the problem.<br>
<br>
The core issue was that canConvertValue and convertValue in SROA were<br>
handling different bitwidth integers by doing a zext of the integer. It<br>
wouldn't do a trunc though, only a zext! This would in turn lead SROA to<br>
form an i24 load from an i24 alloca, zext it to i32, and then use it.<br>
This would at least produce the wrong value for big-endian systems.<br>
<br>
One of my many false starts here was to correct the computation for<br>
big-endian systems by shifting. But this doesn't actually work because<br>
the original code has a 64-bit store to the entire 8 bytes, and a 32-bit<br>
load of the last 4 bytes, and because the alloc size is 8 bytes, we<br>
can't lose that last (least significant if bigendian) byte! The real<br>
problem here is that we're forming an i24 load in SROA which is actually<br>
not sufficiently wide to load all of the necessary bits here. The source<br>
has an i32 load, and SROA needs to form that as well.<br>
<br>
The straightforward way to do this is to disable the zext logic in<br>
canConvertValue and convertValue, forcing us to actually load all<br>
32-bits. This seems like a really good change, but it in turn breaks<br>
several other parts of SROA.<br>
<br>
First in the chain of knock-on failures, we had places where we were<br>
doing integer-widening promotion even though some of the integer loads<br>
or stores extended *past the end* of the alloca's memory! There was even<br>
a comment about preventing this, but it only prevented the case where<br>
the type had a different bit size from its store size. So I added checks<br>
to handle the cases where we actually have a widened load or store and<br>
to avoid trying to special integer widening promotion in those cases.<br>
<br>
Second, we actually rely on the ability to promote in the face of loads<br>
past the end of an alloca! This is important so that we can (for<br>
example) speculate loads around PHI nodes to do more promotion. The bits<br>
loaded are garbage, but as long as they aren't used and the alignment is<br>
suitable high (which it wasn't in the test case!) this is "fine". And we<br>
can't stop promoting here, lots of things stop working well if we do. So<br>
we need to add specific logic to handle the extension (and truncation)<br>
case, but *only* where that extension or truncation are over bytes that<br>
*are outside the alloca's allocated storage* and thus totally bogus to<br>
load or store.<br>
<br>
And of course, once we add back this correct handling of extension or<br>
truncation, we need to correctly handle bigendian systems to avoid<br>
re-introducing the exact bug that started us off on this chain of misery<br>
in the first place, but this time even more subtle as it only happens<br>
along speculated loads atop a PHI node.<br>
<br>
I've ported an existing test for PHI speculation to the big-endian test<br>
file and checked that we get that part correct, and I've added several<br>
more interesting big-endian test cases that should help check that we're<br>
getting this correct.<br>
<br>
Fun times.<br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/Scalar/SROA.cpp<br>
    llvm/trunk/test/Transforms/SROA/basictest.ll<br>
    llvm/trunk/test/Transforms/SROA/big-endian.ll<br>
    llvm/trunk/test/Transforms/SROA/phi-and-select.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/SROA.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Transforms_Scalar_SROA.cpp-3Frev-3D242869-26r1-3D242868-26r2-3D242869-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=F1q3VZl0uUG9VIJ7OQ6PWCf2vaejhfp4-rFx45ltBWs&s=zOYwSJT4amTsE8k23aQ42vLrxDaYI3S4V151PyQonFI&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SROA.cpp?rev=242869&r1=242868&r2=242869&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/SROA.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/SROA.cpp Tue Jul 21 22:32:42 2015<br>
@@ -1847,10 +1847,17 @@ static unsigned getAdjustedAlignment(Ins<br>
 static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy) {<br>
   if (OldTy == NewTy)<br>
     return true;<br>
-  if (IntegerType *OldITy = dyn_cast<IntegerType>(OldTy))<br>
-    if (IntegerType *NewITy = dyn_cast<IntegerType>(NewTy))<br>
-      if (NewITy->getBitWidth() >= OldITy->getBitWidth())<br>
-        return true;<br>
+<br>
+  // For integer types, we can't handle any bit-width differences. This would<br>
+  // break both vector conversions with extension and introduce endianness<br>
+  // issues when in conjunction with loads and stores.<br>
+  if (isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) {<br>
+    assert(cast<IntegerType>(OldTy)->getBitWidth() !=<br>
+               cast<IntegerType>(NewTy)->getBitWidth() &&<br>
+           "We can't have the same bitwidth for different int types");<br>
+    return false;<br>
+  }<br>
+<br>
   if (DL.getTypeSizeInBits(NewTy) != DL.getTypeSizeInBits(OldTy))<br>
     return false;<br>
   if (!NewTy->isSingleValueType() || !OldTy->isSingleValueType())<br>
@@ -1885,10 +1892,8 @@ static Value *convertValue(const DataLay<br>
   if (OldTy == NewTy)<br>
     return V;<br>
<br>
-  if (IntegerType *OldITy = dyn_cast<IntegerType>(OldTy))<br>
-    if (IntegerType *NewITy = dyn_cast<IntegerType>(NewTy))<br>
-      if (NewITy->getBitWidth() > OldITy->getBitWidth())<br>
-        return IRB.CreateZExt(V, NewITy);<br>
+  assert(!(isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) &&<br>
+         "Integer types must be the exact same to convert.");<br>
<br>
   // See if we need inttoptr for this type pair. A cast involving both scalars<br>
   // and vectors requires and additional bitcast.<br>
@@ -2134,6 +2139,9 @@ static bool isIntegerWideningViableForSl<br>
   if (LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {<br>
     if (LI->isVolatile())<br>
       return false;<br>
+    // We can't handle loads that extend past the allocated memory.<br>
+    if (DL.getTypeStoreSize(LI->getType()) > Size)<br>
+      return false;<br>
     // Note that we don't count vector loads or stores as whole-alloca<br>
     // operations which enable integer widening because we would prefer to use<br>
     // vector widening instead.<br>
@@ -2152,6 +2160,9 @@ static bool isIntegerWideningViableForSl<br>
     Type *ValueTy = SI->getValueOperand()->getType();<br>
     if (SI->isVolatile())<br>
       return false;<br>
+    // We can't handle stores that extend past the allocated memory.<br>
+    if (DL.getTypeStoreSize(ValueTy) > Size)<br>
+      return false;<br>
     // Note that we don't count vector loads or stores as whole-alloca<br>
     // operations which enable integer widening because we would prefer to use<br>
     // vector widening instead.<br>
@@ -2585,6 +2596,7 @@ private:<br>
<br>
     Type *TargetTy = IsSplit ? Type::getIntNTy(LI.getContext(), SliceSize * 8)<br>
                              : LI.getType();<br>
+    const bool IsLoadPastEnd = DL.getTypeStoreSize(TargetTy) > SliceSize;<br>
     bool IsPtrAdjusted = false;<br>
     Value *V;<br>
     if (VecTy) {<br>
@@ -2592,13 +2604,27 @@ private:<br>
     } else if (IntTy && LI.getType()->isIntegerTy()) {<br>
       V = rewriteIntegerLoad(LI);<br>
     } else if (NewBeginOffset == NewAllocaBeginOffset &&<br>
-               canConvertValue(DL, NewAllocaTy, LI.getType())) {<br>
+               NewEndOffset == NewAllocaEndOffset &&<br>
+               (canConvertValue(DL, NewAllocaTy, TargetTy) ||<br>
+                (IsLoadPastEnd && NewAllocaTy->isIntegerTy() &&<br>
+                 TargetTy->isIntegerTy()))) {<br>
       LoadInst *NewLI = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(),<br>
                                               LI.isVolatile(), LI.getName());<br>
       if (LI.isVolatile())<br>
         NewLI->setAtomic(LI.getOrdering(), LI.getSynchScope());<br>
-<br>
       V = NewLI;<br>
+<br>
+      // If this is an integer load past the end of the slice (which means the<br>
+      // bytes outside the slice are undef or this load is dead) just forcibly<br>
+      // fix the integer size with correct handling of endianness.<br>
+      if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))<br>
+        if (auto *TITy = dyn_cast<IntegerType>(TargetTy))<br>
+          if (AITy->getBitWidth() < TITy->getBitWidth()) {<br>
+            V = IRB.CreateZExt(V, TITy, "load.ext");<br>
+            if (DL.isBigEndian())<br>
+              V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),<br>
+                                "endian_shift");<br>
+          }<br>
     } else {<br>
       Type *LTy = TargetTy->getPointerTo();<br>
       LoadInst *NewLI = IRB.CreateAlignedLoad(getNewAllocaSlicePtr(IRB, LTy),<br>
@@ -2718,10 +2744,25 @@ private:<br>
     if (IntTy && V->getType()->isIntegerTy())<br>
       return rewriteIntegerStore(V, SI);<br>
<br>
+    const bool IsStorePastEnd = DL.getTypeStoreSize(V->getType()) > SliceSize;<br>
     StoreInst *NewSI;<br>
     if (NewBeginOffset == NewAllocaBeginOffset &&<br>
         NewEndOffset == NewAllocaEndOffset &&<br>
-        canConvertValue(DL, V->getType(), NewAllocaTy)) {<br>
+        (canConvertValue(DL, V->getType(), NewAllocaTy) ||<br>
+         (IsStorePastEnd && NewAllocaTy->isIntegerTy() &&<br>
+          V->getType()->isIntegerTy()))) {<br>
+      // If this is an integer store past the end of slice (and thus the bytes<br>
+      // past that point are irrelevant or this is unreachable), truncate the<br>
+      // value prior to storing.<br>
+      if (auto *VITy = dyn_cast<IntegerType>(V->getType()))<br>
+        if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))<br>
+          if (VITy->getBitWidth() > AITy->getBitWidth()) {<br>
+            if (DL.isBigEndian())<br>
+              V = IRB.CreateLShr(V, VITy->getBitWidth() - AITy->getBitWidth(),<br>
+                                 "endian_shift");<br>
+            V = IRB.CreateTrunc(V, AITy, "load.trunc");<br>
+          }<br>
+<br>
       V = convertValue(DL, IRB, V, NewAllocaTy);<br>
       NewSI = IRB.CreateAlignedStore(V, &NewAI, NewAI.getAlignment(),<br>
                                      SI.isVolatile());<br>
<br>
Modified: llvm/trunk/test/Transforms/SROA/basictest.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Transforms_SROA_basictest.ll-3Frev-3D242869-26r1-3D242868-26r2-3D242869-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=F1q3VZl0uUG9VIJ7OQ6PWCf2vaejhfp4-rFx45ltBWs&s=EMscuRQL0GyZS3b8JVrENUQGjooY4_Fx10gsW2-AZW8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SROA/basictest.ll?rev=242869&r1=242868&r2=242869&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SROA/basictest.ll (original)<br>
+++ llvm/trunk/test/Transforms/SROA/basictest.ll Tue Jul 21 22:32:42 2015<br>
@@ -1195,20 +1195,24 @@ entry:<br>
   %a = alloca <{ i1 }>, align 8<br>
   %b = alloca <{ i1 }>, align 8<br>
 ; CHECK:      %[[a:.*]] = alloca i8, align 8<br>
+; CHECK-NEXT: %[[b:.*]] = alloca i8, align 8<br>
<br>
   %b.i1 = bitcast <{ i1 }>* %b to i1*<br>
   store i1 %x, i1* %b.i1, align 8<br>
   %b.i8 = bitcast <{ i1 }>* %b to i8*<br>
   %foo = load i8, i8* %b.i8, align 1<br>
-; CHECK-NEXT: %[[ext:.*]] = zext i1 %x to i8<br>
-; CHECK-NEXT: store i8 %[[ext]], i8* %[[a]], align 8<br>
-; CHECK-NEXT: {{.*}} = load i8, i8* %[[a]], align 8<br>
+; CHECK-NEXT: %[[b_cast:.*]] = bitcast i8* %[[b]] to i1*<br>
+; CHECK-NEXT: store i1 %x, i1* %[[b_cast]], align 8<br>
+; CHECK-NEXT: {{.*}} = load i8, i8* %[[b]], align 8<br>
<br>
   %a.i8 = bitcast <{ i1 }>* %a to i8*<br>
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a.i8, i8* %b.i8, i32 1, i32 1, i1 false) nounwind<br>
   %bar = load i8, i8* %a.i8, align 1<br>
   %a.i1 = getelementptr inbounds <{ i1 }>, <{ i1 }>* %a, i32 0, i32 0<br>
   %baz = load i1, i1* %a.i1, align 1<br>
+; CHECK-NEXT: %[[copy:.*]] = load i8, i8* %[[b]], align 8<br>
+; CHECK-NEXT: store i8 %[[copy]], i8* %[[a]], align 8<br>
+; CHECK-NEXT: {{.*}} = load i8, i8* %[[a]], align 8<br>
 ; CHECK-NEXT: %[[a_cast:.*]] = bitcast i8* %[[a]] to i1*<br>
 ; CHECK-NEXT: {{.*}} = load i1, i1* %[[a_cast]], align 8<br>
<br>
<br>
Modified: llvm/trunk/test/Transforms/SROA/big-endian.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Transforms_SROA_big-2Dendian.ll-3Frev-3D242869-26r1-3D242868-26r2-3D242869-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=F1q3VZl0uUG9VIJ7OQ6PWCf2vaejhfp4-rFx45ltBWs&s=vr4lvieHXkvuSHCx3QIc1K3pr5czd6Ou3JzwCor5iJY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SROA/big-endian.ll?rev=242869&r1=242868&r2=242869&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SROA/big-endian.ll (original)<br>
+++ llvm/trunk/test/Transforms/SROA/big-endian.ll Tue Jul 21 22:32:42 2015<br>
@@ -112,3 +112,126 @@ entry:<br>
 ; CHECK-NEXT: %[[ret:.*]] = zext i56 %[[insert4]] to i64<br>
 ; CHECK-NEXT: ret i64 %[[ret]]<br>
 }<br>
+<br>
+define i64 @PR14132(i1 %flag) {<br>
+; CHECK-LABEL: @PR14132(<br>
+; Here we form a PHI-node by promoting the pointer alloca first, and then in<br>
+; order to promote the other two allocas, we speculate the load of the<br>
+; now-phi-node-pointer. In doing so we end up loading a 64-bit value from an i8<br>
+; alloca. While this is a bit dubious, we were asserting on trying to<br>
+; rewrite it. The trick is that the code using the value may carefully take<br>
+; steps to only use the not-undef bits, and so we need to at least loosely<br>
+; support this. This test is particularly interesting because how we handle<br>
+; a load of an i64 from an i8 alloca is dependent on endianness.<br>
+entry:<br>
+  %a = alloca i64, align 8<br>
+  %b = alloca i8, align 8<br>
+  %ptr = alloca i64*, align 8<br>
+; CHECK-NOT: alloca<br>
+<br>
+  %ptr.cast = bitcast i64** %ptr to i8**<br>
+  store i64 0, i64* %a<br>
+  store i8 1, i8* %b<br>
+  store i64* %a, i64** %ptr<br>
+  br i1 %flag, label %if.then, label %if.end<br>
+<br>
+if.then:<br>
+  store i8* %b, i8** %ptr.cast<br>
+  br label %if.end<br>
+; CHECK-NOT: store<br>
+; CHECK: %[[ext:.*]] = zext i8 1 to i64<br>
+; CHECK: %[[shift:.*]] = shl i64 %[[ext]], 56<br>
+<br>
+if.end:<br>
+  %tmp = load i64*, i64** %ptr<br>
+  %result = load i64, i64* %tmp<br>
+; CHECK-NOT: load<br>
+; CHECK: %[[result:.*]] = phi i64 [ %[[shift]], %if.then ], [ 0, %entry ]<br>
+<br>
+  ret i64 %result<br>
+; CHECK-NEXT: ret i64 %[[result]]<br>
+}<br>
+<br>
+declare void @f(i64 %x, i32 %y)<br>
+<br>
+define void @test3() {<br>
+; CHECK-LABEL: @test3(<br>
+;<br>
+; This is a test that specifically exercises the big-endian lowering because it<br>
+; ends up splitting a 64-bit integer into two smaller integers and has a number<br>
+; of tricky aspects (the i24 type) that make that hard. Historically, SROA<br>
+; would miscompile this by either dropping a most significant byte or least<br>
+; significant byte due to shrinking the [4,8) slice to an i24, or by failing to<br>
+; move the bytes around correctly.<br>
+;<br>
+; The magical number 34494054408 is used because it has bits set in various<br>
+; bytes so that it is clear if those bytes fail to be propagated.<br>
+;<br>
+; If you're debugging this, rather than using the direct magical numbers, run<br>
+; the IR through '-sroa -instcombine'. With '-instcombine' these will be<br>
+; constant folded, and if the i64 doesn't round-trip correctly, you've found<br>
+; a bug!<br>
+;<br>
+entry:<br>
+  %a = alloca { i32, i24 }, align 4<br>
+; CHECK-NOT: alloca<br>
+<br>
+  %tmp0 = bitcast { i32, i24 }* %a to i64*<br>
+  store i64 34494054408, i64* %tmp0<br>
+  %tmp1 = load i64, i64* %tmp0, align 4<br>
+  %tmp2 = bitcast { i32, i24 }* %a to i32*<br>
+  %tmp3 = load i32, i32* %tmp2, align 4<br>
+; CHECK: %[[HI_EXT:.*]] = zext i32 134316040 to i64<br>
+; CHECK: %[[HI_INPUT:.*]] = and i64 undef, -4294967296<br>
+; CHECK: %[[HI_MERGE:.*]] = or i64 %[[HI_INPUT]], %[[HI_EXT]]<br>
+; CHECK: %[[LO_EXT:.*]] = zext i32 8 to i64<br>
+; CHECK: %[[LO_SHL:.*]] = shl i64 %[[LO_EXT]], 32<br>
+; CHECK: %[[LO_INPUT:.*]] = and i64 %[[HI_MERGE]], 4294967295<br>
+; CHECK: %[[LO_MERGE:.*]] = or i64 %[[LO_INPUT]], %[[LO_SHL]]<br>
+<br>
+  call void @f(i64 %tmp1, i32 %tmp3)<br>
+; CHECK: call void @f(i64 %[[LO_MERGE]], i32 8)<br>
+  ret void<br>
+; CHECK: ret void<br>
+}<br>
+<br>
+define void @test4() {<br>
+; CHECK-LABEL: @test4<br>
+;<br>
+; Much like @test3, this is specifically testing big-endian management of data.<br>
+; Also similarly, it uses constants with particular bits set to help track<br>
+; whether values are corrupted, and can be easily evaluated by running through<br>
+; -instcombine to see that the i64 round-trips.<br>
+;<br>
+entry:<br>
+  %a = alloca { i32, i24 }, align 4<br>
+  %a2 = alloca i64, align 4<br>
+; CHECK-NOT: alloca<br>
+<br>
+  store i64 34494054408, i64* %a2<br>
+  %tmp0 = bitcast { i32, i24 }* %a to i8*<br>
+  %tmp1 = bitcast i64* %a2 to i8*<br>
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp0, i8* %tmp1, i64 8, i32 4, i1 false)<br>
+; CHECK: %[[LO_SHR:.*]] = lshr i64 34494054408, 32<br>
+; CHECK: %[[LO_START:.*]] = trunc i64 %[[LO_SHR]] to i32<br>
+; CHECK: %[[HI_START:.*]] = trunc i64 34494054408 to i32<br>
+<br>
+  %tmp2 = bitcast { i32, i24 }* %a to i64*<br>
+  %tmp3 = load i64, i64* %tmp2, align 4<br>
+  %tmp4 = bitcast { i32, i24 }* %a to i32*<br>
+  %tmp5 = load i32, i32* %tmp4, align 4<br>
+; CHECK: %[[HI_EXT:.*]] = zext i32 %[[HI_START]] to i64<br>
+; CHECK: %[[HI_INPUT:.*]] = and i64 undef, -4294967296<br>
+; CHECK: %[[HI_MERGE:.*]] = or i64 %[[HI_INPUT]], %[[HI_EXT]]<br>
+; CHECK: %[[LO_EXT:.*]] = zext i32 %[[LO_START]] to i64<br>
+; CHECK: %[[LO_SHL:.*]] = shl i64 %[[LO_EXT]], 32<br>
+; CHECK: %[[LO_INPUT:.*]] = and i64 %[[HI_MERGE]], 4294967295<br>
+; CHECK: %[[LO_MERGE:.*]] = or i64 %[[LO_INPUT]], %[[LO_SHL]]<br>
+<br>
+  call void @f(i64 %tmp3, i32 %tmp5)<br>
+; CHECK: call void @f(i64 %[[LO_MERGE]], i32 %[[LO_START]])<br>
+  ret void<br>
+; CHECK: ret void<br>
+}<br>
+<br>
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)<br>
<br>
Modified: llvm/trunk/test/Transforms/SROA/phi-and-select.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Transforms_SROA_phi-2Dand-2Dselect.ll-3Frev-3D242869-26r1-3D242868-26r2-3D242869-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=F1q3VZl0uUG9VIJ7OQ6PWCf2vaejhfp4-rFx45ltBWs&s=JduhZQfIiKUwydIq4RE3-wx71DmQELbbfOmgTUXz8XA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SROA/phi-and-select.ll?rev=242869&r1=242868&r2=242869&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SROA/phi-and-select.ll (original)<br>
+++ llvm/trunk/test/Transforms/SROA/phi-and-select.ll Tue Jul 21 22:32:42 2015<br>
@@ -438,26 +438,26 @@ define i64 @PR14132(i1 %flag) {<br>
 ; steps to only use the not-undef bits, and so we need to at least loosely<br>
 ; support this..<br>
 entry:<br>
-  %a = alloca i64<br>
-  %b = alloca i8<br>
-  %ptr = alloca i64*<br>
+  %a = alloca i64, align 8<br>
+  %b = alloca i8, align 8<br>
+  %ptr = alloca i64*, align 8<br>
 ; CHECK-NOT: alloca<br>
<br>
   %ptr.cast = bitcast i64** %ptr to i8**<br>
-  store i64 0, i64* %a<br>
-  store i8 1, i8* %b<br>
-  store i64* %a, i64** %ptr<br>
+  store i64 0, i64* %a, align 8<br>
+  store i8 1, i8* %b, align 8<br>
+  store i64* %a, i64** %ptr, align 8<br>
   br i1 %flag, label %if.then, label %if.end<br>
<br>
 if.then:<br>
-  store i8* %b, i8** %ptr.cast<br>
+  store i8* %b, i8** %ptr.cast, align 8<br>
   br label %if.end<br>
 ; CHECK-NOT: store<br>
 ; CHECK: %[[ext:.*]] = zext i8 1 to i64<br>
<br>
 if.end:<br>
-  %tmp = load i64*, i64** %ptr<br>
-  %result = load i64, i64* %tmp<br>
+  %tmp = load i64*, i64** %ptr, align 8<br>
+  %result = load i64, i64* %tmp, align 8<br>
 ; CHECK-NOT: load<br>
 ; CHECK: %[[result:.*]] = phi i64 [ %[[ext]], %if.then ], [ 0, %entry ]<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>