1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4target datalayout = "e-i64:64-f80:128-n8:16:32:64" 5target triple = "x86_64-unknown-linux-gnu" 6 7%A__vtbl = type { ptr, ptr } 8%A = type { ptr } 9%B = type { ptr, i64 } 10 11@A__vtblZ = constant %A__vtbl { ptr null, ptr @A.foo } 12 13declare i32 @A.foo(ptr nocapture %this) 14 15define void @storeA(ptr %a.ptr) { 16; CHECK-LABEL: @storeA( 17; CHECK-NEXT: store ptr @A__vtblZ, ptr [[A_PTR:%.*]], align 8 18; CHECK-NEXT: ret void 19; 20 store %A { ptr @A__vtblZ }, ptr %a.ptr, align 8 21 ret void 22} 23 24define void @storeB(ptr %b.ptr) { 25; CHECK-LABEL: @storeB( 26; CHECK-NEXT: store ptr null, ptr [[B_PTR:%.*]], align 8 27; CHECK-NEXT: [[B_PTR_REPACK1:%.*]] = getelementptr inbounds nuw i8, ptr [[B_PTR]], i64 8 28; CHECK-NEXT: store i64 42, ptr [[B_PTR_REPACK1]], align 8 29; CHECK-NEXT: ret void 30; 31 store %B { ptr null, i64 42 }, ptr %b.ptr, align 8 32 ret void 33} 34 35define void @storeStructOfA(ptr %sa.ptr) { 36; CHECK-LABEL: @storeStructOfA( 37; CHECK-NEXT: store ptr @A__vtblZ, ptr [[SA_PTR:%.*]], align 8 38; CHECK-NEXT: ret void 39; 40 store { %A } { %A { ptr @A__vtblZ } }, ptr %sa.ptr, align 8 41 ret void 42} 43 44define void @storeArrayOfA(ptr %aa.ptr) { 45; CHECK-LABEL: @storeArrayOfA( 46; CHECK-NEXT: store ptr @A__vtblZ, ptr [[AA_PTR:%.*]], align 8 47; CHECK-NEXT: ret void 48; 49 store [1 x %A] [%A { ptr @A__vtblZ }], ptr %aa.ptr, align 8 50 ret void 51} 52 53; UTC_ARGS: --disable 54define void @storeLargeArrayOfA(ptr %aa.ptr) { 55; CHECK-LABEL: @storeLargeArrayOfA( 56; CHECK-NEXT: store [2000 x %A] 57; CHECK-NEXT: ret void 58; 59 %i1 = insertvalue [2000 x %A] poison, %A { ptr @A__vtblZ }, 1 60 store [2000 x %A] %i1, ptr %aa.ptr, align 8 61 ret void 62} 63; UTC_ARGS: --enable 64 65define void @storeStructOfArrayOfA(ptr %saa.ptr) { 66; CHECK-LABEL: @storeStructOfArrayOfA( 67; CHECK-NEXT: store ptr @A__vtblZ, ptr [[SAA_PTR:%.*]], align 8 68; CHECK-NEXT: ret void 69; 70 store { [1 x %A] } { [1 x %A] [%A { ptr @A__vtblZ }] }, ptr %saa.ptr, align 8 71 ret void 72} 73 74define void @storeArrayOfB(ptr %ab.ptr, [2 x %B] %ab) { 75; CHECK-LABEL: @storeArrayOfB( 76; CHECK-NEXT: [[AB_ELT:%.*]] = extractvalue [2 x %B] [[AB:%.*]], 0 77; CHECK-NEXT: [[AB_ELT_ELT:%.*]] = extractvalue [[B:%.*]] [[AB_ELT]], 0 78; CHECK-NEXT: store ptr [[AB_ELT_ELT]], ptr [[AB_PTR:%.*]], align 8 79; CHECK-NEXT: [[AB_PTR_REPACK3:%.*]] = getelementptr inbounds nuw i8, ptr [[AB_PTR]], i64 8 80; CHECK-NEXT: [[AB_ELT_ELT4:%.*]] = extractvalue [[B]] [[AB_ELT]], 1 81; CHECK-NEXT: store i64 [[AB_ELT_ELT4]], ptr [[AB_PTR_REPACK3]], align 8 82; CHECK-NEXT: [[AB_PTR_REPACK1:%.*]] = getelementptr inbounds nuw i8, ptr [[AB_PTR]], i64 16 83; CHECK-NEXT: [[AB_ELT2:%.*]] = extractvalue [2 x %B] [[AB]], 1 84; CHECK-NEXT: [[AB_ELT2_ELT:%.*]] = extractvalue [[B]] [[AB_ELT2]], 0 85; CHECK-NEXT: store ptr [[AB_ELT2_ELT]], ptr [[AB_PTR_REPACK1]], align 8 86; CHECK-NEXT: [[AB_PTR_REPACK1_REPACK5:%.*]] = getelementptr inbounds nuw i8, ptr [[AB_PTR]], i64 24 87; CHECK-NEXT: [[AB_ELT2_ELT6:%.*]] = extractvalue [[B]] [[AB_ELT2]], 1 88; CHECK-NEXT: store i64 [[AB_ELT2_ELT6]], ptr [[AB_PTR_REPACK1_REPACK5]], align 8 89; CHECK-NEXT: ret void 90; 91 store [2 x %B] %ab, ptr %ab.ptr, align 8 92 ret void 93} 94 95define %A @loadA(ptr %a.ptr) { 96; CHECK-LABEL: @loadA( 97; CHECK-NEXT: [[DOTUNPACK:%.*]] = load ptr, ptr [[A_PTR:%.*]], align 8 98; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[A:%.*]] poison, ptr [[DOTUNPACK]], 0 99; CHECK-NEXT: ret [[A]] [[TMP1]] 100; 101 %1 = load %A, ptr %a.ptr, align 8 102 ret %A %1 103} 104 105define %B @loadB(ptr %b.ptr) { 106; CHECK-LABEL: @loadB( 107; CHECK-NEXT: [[DOTUNPACK:%.*]] = load ptr, ptr [[B_PTR:%.*]], align 8 108; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[B:%.*]] poison, ptr [[DOTUNPACK]], 0 109; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[B_PTR]], i64 8 110; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load i64, ptr [[DOTELT1]], align 8 111; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[B]] [[TMP1]], i64 [[DOTUNPACK2]], 1 112; CHECK-NEXT: ret [[B]] [[TMP2]] 113; 114 %1 = load %B, ptr %b.ptr, align 8 115 ret %B %1 116} 117 118define { %A } @loadStructOfA(ptr %sa.ptr) { 119; CHECK-LABEL: @loadStructOfA( 120; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load ptr, ptr [[SA_PTR:%.*]], align 8 121; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [[A:%.*]] poison, ptr [[DOTUNPACK_UNPACK]], 0 122; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { [[A]] } poison, [[A]] [[DOTUNPACK1]], 0 123; CHECK-NEXT: ret { [[A]] } [[TMP1]] 124; 125 %1 = load { %A }, ptr %sa.ptr, align 8 126 ret { %A } %1 127} 128 129define [1 x %A] @loadArrayOfA(ptr %aa.ptr) { 130; CHECK-LABEL: @loadArrayOfA( 131; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load ptr, ptr [[AA_PTR:%.*]], align 8 132; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [[A:%.*]] poison, ptr [[DOTUNPACK_UNPACK]], 0 133; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [1 x %A] poison, [[A]] [[DOTUNPACK1]], 0 134; CHECK-NEXT: ret [1 x %A] [[TMP1]] 135; 136 %1 = load [1 x %A], ptr %aa.ptr, align 8 137 ret [1 x %A] %1 138} 139 140define { [1 x %A] } @loadStructOfArrayOfA(ptr %saa.ptr) { 141; CHECK-LABEL: @loadStructOfArrayOfA( 142; CHECK-NEXT: [[DOTUNPACK_UNPACK_UNPACK:%.*]] = load ptr, ptr [[SAA_PTR:%.*]], align 8 143; CHECK-NEXT: [[DOTUNPACK_UNPACK2:%.*]] = insertvalue [[A:%.*]] poison, ptr [[DOTUNPACK_UNPACK_UNPACK]], 0 144; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [1 x %A] poison, [[A]] [[DOTUNPACK_UNPACK2]], 0 145; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { [1 x %A] } poison, [1 x %A] [[DOTUNPACK1]], 0 146; CHECK-NEXT: ret { [1 x %A] } [[TMP1]] 147; 148 %1 = load { [1 x %A] }, ptr %saa.ptr, align 8 149 ret { [1 x %A] } %1 150} 151 152define { %A } @structOfA(ptr %sa.ptr) { 153; CHECK-LABEL: @structOfA( 154; CHECK-NEXT: store ptr @A__vtblZ, ptr [[SA_PTR:%.*]], align 8 155; CHECK-NEXT: ret { [[A:%.*]] } { [[A]] { ptr @A__vtblZ } } 156; 157 store { %A } { %A { ptr @A__vtblZ } }, ptr %sa.ptr, align 8 158 %1 = load { %A }, ptr %sa.ptr, align 8 159 ret { %A } %1 160} 161 162define %B @structB(ptr %b.ptr) { 163; CHECK-LABEL: @structB( 164; CHECK-NEXT: store ptr null, ptr [[B_PTR:%.*]], align 8 165; CHECK-NEXT: [[B_PTR_REPACK1:%.*]] = getelementptr inbounds nuw i8, ptr [[B_PTR]], i64 8 166; CHECK-NEXT: store i64 42, ptr [[B_PTR_REPACK1]], align 8 167; CHECK-NEXT: ret [[B:%.*]] { ptr null, i64 42 } 168; 169 store %B { ptr null, i64 42 }, ptr %b.ptr, align 8 170 %1 = load %B, ptr %b.ptr, align 8 171 ret %B %1 172} 173 174define [2 x %B] @loadArrayOfB(ptr %ab.ptr) { 175; CHECK-LABEL: @loadArrayOfB( 176; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load ptr, ptr [[AB_PTR:%.*]], align 8 177; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[B:%.*]] poison, ptr [[DOTUNPACK_UNPACK]], 0 178; CHECK-NEXT: [[DOTUNPACK_ELT3:%.*]] = getelementptr inbounds nuw i8, ptr [[AB_PTR]], i64 8 179; CHECK-NEXT: [[DOTUNPACK_UNPACK4:%.*]] = load i64, ptr [[DOTUNPACK_ELT3]], align 8 180; CHECK-NEXT: [[DOTUNPACK5:%.*]] = insertvalue [[B]] [[TMP1]], i64 [[DOTUNPACK_UNPACK4]], 1 181; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [2 x %B] poison, [[B]] [[DOTUNPACK5]], 0 182; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[AB_PTR]], i64 16 183; CHECK-NEXT: [[DOTUNPACK2_UNPACK:%.*]] = load ptr, ptr [[DOTELT1]], align 8 184; CHECK-NEXT: [[TMP3:%.*]] = insertvalue [[B]] poison, ptr [[DOTUNPACK2_UNPACK]], 0 185; CHECK-NEXT: [[DOTUNPACK2_ELT6:%.*]] = getelementptr inbounds nuw i8, ptr [[AB_PTR]], i64 24 186; CHECK-NEXT: [[DOTUNPACK2_UNPACK7:%.*]] = load i64, ptr [[DOTUNPACK2_ELT6]], align 8 187; CHECK-NEXT: [[DOTUNPACK28:%.*]] = insertvalue [[B]] [[TMP3]], i64 [[DOTUNPACK2_UNPACK7]], 1 188; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [2 x %B] [[TMP2]], [[B]] [[DOTUNPACK28]], 1 189; CHECK-NEXT: ret [2 x %B] [[TMP4]] 190; 191 %1 = load [2 x %B], ptr %ab.ptr, align 8 192 ret [2 x %B] %1 193} 194 195define [2000 x %B] @loadLargeArrayOfB(ptr %ab.ptr) { 196; CHECK-LABEL: @loadLargeArrayOfB( 197; CHECK-NEXT: [[TMP1:%.*]] = load [2000 x %B], ptr [[AB_PTR:%.*]], align 8 198; CHECK-NEXT: ret [2000 x %B] [[TMP1]] 199; 200 %1 = load [2000 x %B], ptr %ab.ptr, align 8 201 ret [2000 x %B] %1 202} 203 204%struct.S = type <{ i8, %struct.T }> 205%struct.T = type { i32, i32 } 206 207; Make sure that we do not increase alignment of packed struct element 208define i32 @packed_alignment(ptr dereferenceable(9) %s) { 209; CHECK-LABEL: @packed_alignment( 210; CHECK-NEXT: [[TV_ELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[S:%.*]], i64 5 211; CHECK-NEXT: [[TV_UNPACK2:%.*]] = load i32, ptr [[TV_ELT1]], align 1 212; CHECK-NEXT: ret i32 [[TV_UNPACK2]] 213; 214 %t = getelementptr inbounds %struct.S, ptr %s, i32 0, i32 1 215 %tv = load %struct.T, ptr %t, align 1 216 %v = extractvalue %struct.T %tv, 1 217 ret i32 %v 218} 219 220%struct.U = type {i8, i8, i8, i8, i8, i8, i8, i8, i64} 221 222define void @check_alignment(ptr %u, ptr %v) { 223; CHECK-LABEL: @check_alignment( 224; CHECK-NEXT: [[DOTUNPACK:%.*]] = load i8, ptr [[U:%.*]], align 8 225; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 1 226; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load i8, ptr [[DOTELT1]], align 1 227; CHECK-NEXT: [[DOTELT3:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 2 228; CHECK-NEXT: [[DOTUNPACK4:%.*]] = load i8, ptr [[DOTELT3]], align 2 229; CHECK-NEXT: [[DOTELT5:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 3 230; CHECK-NEXT: [[DOTUNPACK6:%.*]] = load i8, ptr [[DOTELT5]], align 1 231; CHECK-NEXT: [[DOTELT7:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 4 232; CHECK-NEXT: [[DOTUNPACK8:%.*]] = load i8, ptr [[DOTELT7]], align 4 233; CHECK-NEXT: [[DOTELT9:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 5 234; CHECK-NEXT: [[DOTUNPACK10:%.*]] = load i8, ptr [[DOTELT9]], align 1 235; CHECK-NEXT: [[DOTELT11:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 6 236; CHECK-NEXT: [[DOTUNPACK12:%.*]] = load i8, ptr [[DOTELT11]], align 2 237; CHECK-NEXT: [[DOTELT13:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 7 238; CHECK-NEXT: [[DOTUNPACK14:%.*]] = load i8, ptr [[DOTELT13]], align 1 239; CHECK-NEXT: [[DOTELT15:%.*]] = getelementptr inbounds nuw i8, ptr [[U]], i64 8 240; CHECK-NEXT: [[DOTUNPACK16:%.*]] = load i64, ptr [[DOTELT15]], align 8 241; CHECK-NEXT: store i8 [[DOTUNPACK]], ptr [[V:%.*]], align 8 242; CHECK-NEXT: [[V_REPACK17:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 1 243; CHECK-NEXT: store i8 [[DOTUNPACK2]], ptr [[V_REPACK17]], align 1 244; CHECK-NEXT: [[V_REPACK19:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 2 245; CHECK-NEXT: store i8 [[DOTUNPACK4]], ptr [[V_REPACK19]], align 2 246; CHECK-NEXT: [[V_REPACK21:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 3 247; CHECK-NEXT: store i8 [[DOTUNPACK6]], ptr [[V_REPACK21]], align 1 248; CHECK-NEXT: [[V_REPACK23:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 4 249; CHECK-NEXT: store i8 [[DOTUNPACK8]], ptr [[V_REPACK23]], align 4 250; CHECK-NEXT: [[V_REPACK25:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 5 251; CHECK-NEXT: store i8 [[DOTUNPACK10]], ptr [[V_REPACK25]], align 1 252; CHECK-NEXT: [[V_REPACK27:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 6 253; CHECK-NEXT: store i8 [[DOTUNPACK12]], ptr [[V_REPACK27]], align 2 254; CHECK-NEXT: [[V_REPACK29:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 7 255; CHECK-NEXT: store i8 [[DOTUNPACK14]], ptr [[V_REPACK29]], align 1 256; CHECK-NEXT: [[V_REPACK31:%.*]] = getelementptr inbounds nuw i8, ptr [[V]], i64 8 257; CHECK-NEXT: store i64 [[DOTUNPACK16]], ptr [[V_REPACK31]], align 8 258; CHECK-NEXT: ret void 259; 260 %1 = load %struct.U, ptr %u 261 store %struct.U %1, ptr %v 262 ret void 263} 264