1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -sroa -S | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Workertarget datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64" 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Workerdefine i8 @test1() { 6*9880d681SAndroid Build Coastguard Worker; We fully promote these to the i24 load or store size, resulting in just masks 7*9880d681SAndroid Build Coastguard Worker; and other operations that instcombine will fold, but no alloca. Note this is 8*9880d681SAndroid Build Coastguard Worker; the same as test12 in basictest.ll, but here we assert big-endian byte 9*9880d681SAndroid Build Coastguard Worker; ordering. 10*9880d681SAndroid Build Coastguard Worker; 11*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test1( 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Workerentry: 14*9880d681SAndroid Build Coastguard Worker %a = alloca [3 x i8] 15*9880d681SAndroid Build Coastguard Worker %b = alloca [3 x i8] 16*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: alloca 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker %a0ptr = getelementptr [3 x i8], [3 x i8]* %a, i64 0, i32 0 19*9880d681SAndroid Build Coastguard Worker store i8 0, i8* %a0ptr 20*9880d681SAndroid Build Coastguard Worker %a1ptr = getelementptr [3 x i8], [3 x i8]* %a, i64 0, i32 1 21*9880d681SAndroid Build Coastguard Worker store i8 0, i8* %a1ptr 22*9880d681SAndroid Build Coastguard Worker %a2ptr = getelementptr [3 x i8], [3 x i8]* %a, i64 0, i32 2 23*9880d681SAndroid Build Coastguard Worker store i8 0, i8* %a2ptr 24*9880d681SAndroid Build Coastguard Worker %aiptr = bitcast [3 x i8]* %a to i24* 25*9880d681SAndroid Build Coastguard Worker %ai = load i24, i24* %aiptr 26*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: store 27*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: load 28*9880d681SAndroid Build Coastguard Worker; CHECK: %[[ext2:.*]] = zext i8 0 to i24 29*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[mask2:.*]] = and i24 undef, -256 30*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert2:.*]] = or i24 %[[mask2]], %[[ext2]] 31*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[ext1:.*]] = zext i8 0 to i24 32*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[shift1:.*]] = shl i24 %[[ext1]], 8 33*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[mask1:.*]] = and i24 %[[insert2]], -65281 34*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert1:.*]] = or i24 %[[mask1]], %[[shift1]] 35*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[ext0:.*]] = zext i8 0 to i24 36*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[shift0:.*]] = shl i24 %[[ext0]], 16 37*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[mask0:.*]] = and i24 %[[insert1]], 65535 38*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert0:.*]] = or i24 %[[mask0]], %[[shift0]] 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Worker %biptr = bitcast [3 x i8]* %b to i24* 41*9880d681SAndroid Build Coastguard Worker store i24 %ai, i24* %biptr 42*9880d681SAndroid Build Coastguard Worker %b0ptr = getelementptr [3 x i8], [3 x i8]* %b, i64 0, i32 0 43*9880d681SAndroid Build Coastguard Worker %b0 = load i8, i8* %b0ptr 44*9880d681SAndroid Build Coastguard Worker %b1ptr = getelementptr [3 x i8], [3 x i8]* %b, i64 0, i32 1 45*9880d681SAndroid Build Coastguard Worker %b1 = load i8, i8* %b1ptr 46*9880d681SAndroid Build Coastguard Worker %b2ptr = getelementptr [3 x i8], [3 x i8]* %b, i64 0, i32 2 47*9880d681SAndroid Build Coastguard Worker %b2 = load i8, i8* %b2ptr 48*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: store 49*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: load 50*9880d681SAndroid Build Coastguard Worker; CHECK: %[[shift0:.*]] = lshr i24 %[[insert0]], 16 51*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[trunc0:.*]] = trunc i24 %[[shift0]] to i8 52*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[shift1:.*]] = lshr i24 %[[insert0]], 8 53*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[trunc1:.*]] = trunc i24 %[[shift1]] to i8 54*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[trunc2:.*]] = trunc i24 %[[insert0]] to i8 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Worker %bsum0 = add i8 %b0, %b1 57*9880d681SAndroid Build Coastguard Worker %bsum1 = add i8 %bsum0, %b2 58*9880d681SAndroid Build Coastguard Worker ret i8 %bsum1 59*9880d681SAndroid Build Coastguard Worker; CHECK: %[[sum0:.*]] = add i8 %[[trunc0]], %[[trunc1]] 60*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[sum1:.*]] = add i8 %[[sum0]], %[[trunc2]] 61*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret i8 %[[sum1]] 62*9880d681SAndroid Build Coastguard Worker} 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Workerdefine i64 @test2() { 65*9880d681SAndroid Build Coastguard Worker; Test for various mixed sizes of integer loads and stores all getting 66*9880d681SAndroid Build Coastguard Worker; promoted. 67*9880d681SAndroid Build Coastguard Worker; 68*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test2( 69*9880d681SAndroid Build Coastguard Worker 70*9880d681SAndroid Build Coastguard Workerentry: 71*9880d681SAndroid Build Coastguard Worker %a = alloca [7 x i8] 72*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: alloca 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker %a0ptr = getelementptr [7 x i8], [7 x i8]* %a, i64 0, i32 0 75*9880d681SAndroid Build Coastguard Worker %a1ptr = getelementptr [7 x i8], [7 x i8]* %a, i64 0, i32 1 76*9880d681SAndroid Build Coastguard Worker %a2ptr = getelementptr [7 x i8], [7 x i8]* %a, i64 0, i32 2 77*9880d681SAndroid Build Coastguard Worker %a3ptr = getelementptr [7 x i8], [7 x i8]* %a, i64 0, i32 3 78*9880d681SAndroid Build Coastguard Worker 79*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: store 80*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: load 81*9880d681SAndroid Build Coastguard Worker 82*9880d681SAndroid Build Coastguard Worker %a0i16ptr = bitcast i8* %a0ptr to i16* 83*9880d681SAndroid Build Coastguard Worker store i16 1, i16* %a0i16ptr 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard Worker store i8 1, i8* %a2ptr 86*9880d681SAndroid Build Coastguard Worker; CHECK: %[[mask1:.*]] = and i40 undef, 4294967295 87*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert1:.*]] = or i40 %[[mask1]], 4294967296 88*9880d681SAndroid Build Coastguard Worker 89*9880d681SAndroid Build Coastguard Worker %a3i24ptr = bitcast i8* %a3ptr to i24* 90*9880d681SAndroid Build Coastguard Worker store i24 1, i24* %a3i24ptr 91*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[mask2:.*]] = and i40 %[[insert1]], -4294967041 92*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert2:.*]] = or i40 %[[mask2]], 256 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Worker %a2i40ptr = bitcast i8* %a2ptr to i40* 95*9880d681SAndroid Build Coastguard Worker store i40 1, i40* %a2i40ptr 96*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[ext3:.*]] = zext i40 1 to i56 97*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[mask3:.*]] = and i56 undef, -1099511627776 98*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert3:.*]] = or i56 %[[mask3]], %[[ext3]] 99*9880d681SAndroid Build Coastguard Worker 100*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: store 101*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: load 102*9880d681SAndroid Build Coastguard Worker 103*9880d681SAndroid Build Coastguard Worker %aiptr = bitcast [7 x i8]* %a to i56* 104*9880d681SAndroid Build Coastguard Worker %ai = load i56, i56* %aiptr 105*9880d681SAndroid Build Coastguard Worker %ret = zext i56 %ai to i64 106*9880d681SAndroid Build Coastguard Worker ret i64 %ret 107*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[ext4:.*]] = zext i16 1 to i56 108*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[shift4:.*]] = shl i56 %[[ext4]], 40 109*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[mask4:.*]] = and i56 %[[insert3]], 1099511627775 110*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[insert4:.*]] = or i56 %[[mask4]], %[[shift4]] 111*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[ret:.*]] = zext i56 %[[insert4]] to i64 112*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret i64 %[[ret]] 113*9880d681SAndroid Build Coastguard Worker} 114*9880d681SAndroid Build Coastguard Worker 115*9880d681SAndroid Build Coastguard Workerdefine i64 @PR14132(i1 %flag) { 116*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @PR14132( 117*9880d681SAndroid Build Coastguard Worker; Here we form a PHI-node by promoting the pointer alloca first, and then in 118*9880d681SAndroid Build Coastguard Worker; order to promote the other two allocas, we speculate the load of the 119*9880d681SAndroid Build Coastguard Worker; now-phi-node-pointer. In doing so we end up loading a 64-bit value from an i8 120*9880d681SAndroid Build Coastguard Worker; alloca. While this is a bit dubious, we were asserting on trying to 121*9880d681SAndroid Build Coastguard Worker; rewrite it. The trick is that the code using the value may carefully take 122*9880d681SAndroid Build Coastguard Worker; steps to only use the not-undef bits, and so we need to at least loosely 123*9880d681SAndroid Build Coastguard Worker; support this. This test is particularly interesting because how we handle 124*9880d681SAndroid Build Coastguard Worker; a load of an i64 from an i8 alloca is dependent on endianness. 125*9880d681SAndroid Build Coastguard Workerentry: 126*9880d681SAndroid Build Coastguard Worker %a = alloca i64, align 8 127*9880d681SAndroid Build Coastguard Worker %b = alloca i8, align 8 128*9880d681SAndroid Build Coastguard Worker %ptr = alloca i64*, align 8 129*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: alloca 130*9880d681SAndroid Build Coastguard Worker 131*9880d681SAndroid Build Coastguard Worker %ptr.cast = bitcast i64** %ptr to i8** 132*9880d681SAndroid Build Coastguard Worker store i64 0, i64* %a 133*9880d681SAndroid Build Coastguard Worker store i8 1, i8* %b 134*9880d681SAndroid Build Coastguard Worker store i64* %a, i64** %ptr 135*9880d681SAndroid Build Coastguard Worker br i1 %flag, label %if.then, label %if.end 136*9880d681SAndroid Build Coastguard Worker 137*9880d681SAndroid Build Coastguard Workerif.then: 138*9880d681SAndroid Build Coastguard Worker store i8* %b, i8** %ptr.cast 139*9880d681SAndroid Build Coastguard Worker br label %if.end 140*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: store 141*9880d681SAndroid Build Coastguard Worker; CHECK: %[[ext:.*]] = zext i8 1 to i64 142*9880d681SAndroid Build Coastguard Worker; CHECK: %[[shift:.*]] = shl i64 %[[ext]], 56 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Workerif.end: 145*9880d681SAndroid Build Coastguard Worker %tmp = load i64*, i64** %ptr 146*9880d681SAndroid Build Coastguard Worker %result = load i64, i64* %tmp 147*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: load 148*9880d681SAndroid Build Coastguard Worker; CHECK: %[[result:.*]] = phi i64 [ %[[shift]], %if.then ], [ 0, %entry ] 149*9880d681SAndroid Build Coastguard Worker 150*9880d681SAndroid Build Coastguard Worker ret i64 %result 151*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret i64 %[[result]] 152*9880d681SAndroid Build Coastguard Worker} 153*9880d681SAndroid Build Coastguard Worker 154*9880d681SAndroid Build Coastguard Workerdeclare void @f(i64 %x, i32 %y) 155*9880d681SAndroid Build Coastguard Worker 156*9880d681SAndroid Build Coastguard Workerdefine void @test3() { 157*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test3( 158*9880d681SAndroid Build Coastguard Worker; 159*9880d681SAndroid Build Coastguard Worker; This is a test that specifically exercises the big-endian lowering because it 160*9880d681SAndroid Build Coastguard Worker; ends up splitting a 64-bit integer into two smaller integers and has a number 161*9880d681SAndroid Build Coastguard Worker; of tricky aspects (the i24 type) that make that hard. Historically, SROA 162*9880d681SAndroid Build Coastguard Worker; would miscompile this by either dropping a most significant byte or least 163*9880d681SAndroid Build Coastguard Worker; significant byte due to shrinking the [4,8) slice to an i24, or by failing to 164*9880d681SAndroid Build Coastguard Worker; move the bytes around correctly. 165*9880d681SAndroid Build Coastguard Worker; 166*9880d681SAndroid Build Coastguard Worker; The magical number 34494054408 is used because it has bits set in various 167*9880d681SAndroid Build Coastguard Worker; bytes so that it is clear if those bytes fail to be propagated. 168*9880d681SAndroid Build Coastguard Worker; 169*9880d681SAndroid Build Coastguard Worker; If you're debugging this, rather than using the direct magical numbers, run 170*9880d681SAndroid Build Coastguard Worker; the IR through '-sroa -instcombine'. With '-instcombine' these will be 171*9880d681SAndroid Build Coastguard Worker; constant folded, and if the i64 doesn't round-trip correctly, you've found 172*9880d681SAndroid Build Coastguard Worker; a bug! 173*9880d681SAndroid Build Coastguard Worker; 174*9880d681SAndroid Build Coastguard Workerentry: 175*9880d681SAndroid Build Coastguard Worker %a = alloca { i32, i24 }, align 4 176*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: alloca 177*9880d681SAndroid Build Coastguard Worker 178*9880d681SAndroid Build Coastguard Worker %tmp0 = bitcast { i32, i24 }* %a to i64* 179*9880d681SAndroid Build Coastguard Worker store i64 34494054408, i64* %tmp0 180*9880d681SAndroid Build Coastguard Worker %tmp1 = load i64, i64* %tmp0, align 4 181*9880d681SAndroid Build Coastguard Worker %tmp2 = bitcast { i32, i24 }* %a to i32* 182*9880d681SAndroid Build Coastguard Worker %tmp3 = load i32, i32* %tmp2, align 4 183*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_EXT:.*]] = zext i32 134316040 to i64 184*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_INPUT:.*]] = and i64 undef, -4294967296 185*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_MERGE:.*]] = or i64 %[[HI_INPUT]], %[[HI_EXT]] 186*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_EXT:.*]] = zext i32 8 to i64 187*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_SHL:.*]] = shl i64 %[[LO_EXT]], 32 188*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_INPUT:.*]] = and i64 %[[HI_MERGE]], 4294967295 189*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_MERGE:.*]] = or i64 %[[LO_INPUT]], %[[LO_SHL]] 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Worker call void @f(i64 %tmp1, i32 %tmp3) 192*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f(i64 %[[LO_MERGE]], i32 8) 193*9880d681SAndroid Build Coastguard Worker ret void 194*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 195*9880d681SAndroid Build Coastguard Worker} 196*9880d681SAndroid Build Coastguard Worker 197*9880d681SAndroid Build Coastguard Workerdefine void @test4() { 198*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test4 199*9880d681SAndroid Build Coastguard Worker; 200*9880d681SAndroid Build Coastguard Worker; Much like @test3, this is specifically testing big-endian management of data. 201*9880d681SAndroid Build Coastguard Worker; Also similarly, it uses constants with particular bits set to help track 202*9880d681SAndroid Build Coastguard Worker; whether values are corrupted, and can be easily evaluated by running through 203*9880d681SAndroid Build Coastguard Worker; -instcombine to see that the i64 round-trips. 204*9880d681SAndroid Build Coastguard Worker; 205*9880d681SAndroid Build Coastguard Workerentry: 206*9880d681SAndroid Build Coastguard Worker %a = alloca { i32, i24 }, align 4 207*9880d681SAndroid Build Coastguard Worker %a2 = alloca i64, align 4 208*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: alloca 209*9880d681SAndroid Build Coastguard Worker 210*9880d681SAndroid Build Coastguard Worker store i64 34494054408, i64* %a2 211*9880d681SAndroid Build Coastguard Worker %tmp0 = bitcast { i32, i24 }* %a to i8* 212*9880d681SAndroid Build Coastguard Worker %tmp1 = bitcast i64* %a2 to i8* 213*9880d681SAndroid Build Coastguard Worker call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp0, i8* %tmp1, i64 8, i32 4, i1 false) 214*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_SHR:.*]] = lshr i64 34494054408, 32 215*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_START:.*]] = trunc i64 %[[LO_SHR]] to i32 216*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_START:.*]] = trunc i64 34494054408 to i32 217*9880d681SAndroid Build Coastguard Worker 218*9880d681SAndroid Build Coastguard Worker %tmp2 = bitcast { i32, i24 }* %a to i64* 219*9880d681SAndroid Build Coastguard Worker %tmp3 = load i64, i64* %tmp2, align 4 220*9880d681SAndroid Build Coastguard Worker %tmp4 = bitcast { i32, i24 }* %a to i32* 221*9880d681SAndroid Build Coastguard Worker %tmp5 = load i32, i32* %tmp4, align 4 222*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_EXT:.*]] = zext i32 %[[HI_START]] to i64 223*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_INPUT:.*]] = and i64 undef, -4294967296 224*9880d681SAndroid Build Coastguard Worker; CHECK: %[[HI_MERGE:.*]] = or i64 %[[HI_INPUT]], %[[HI_EXT]] 225*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_EXT:.*]] = zext i32 %[[LO_START]] to i64 226*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_SHL:.*]] = shl i64 %[[LO_EXT]], 32 227*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_INPUT:.*]] = and i64 %[[HI_MERGE]], 4294967295 228*9880d681SAndroid Build Coastguard Worker; CHECK: %[[LO_MERGE:.*]] = or i64 %[[LO_INPUT]], %[[LO_SHL]] 229*9880d681SAndroid Build Coastguard Worker 230*9880d681SAndroid Build Coastguard Worker call void @f(i64 %tmp3, i32 %tmp5) 231*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f(i64 %[[LO_MERGE]], i32 %[[LO_START]]) 232*9880d681SAndroid Build Coastguard Worker ret void 233*9880d681SAndroid Build Coastguard Worker; CHECK: ret void 234*9880d681SAndroid Build Coastguard Worker} 235*9880d681SAndroid Build Coastguard Worker 236*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1) 237