1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes='function(scalarizer)' %s | FileCheck %s 3 4; Check that the scalarizer can handle vector GEPs with scalar indices 5 6@vec = global <4 x ptr> <ptr null, ptr null, ptr null, ptr null> 7@index = global i16 1 8@ptr = global [4 x i16] [i16 1, i16 2, i16 3, i16 4] 9@ptrptr = global ptr null 10 11; constant index 12define void @test1() { 13; CHECK-LABEL: @test1( 14; CHECK-NEXT: bb: 15; CHECK-NEXT: [[TMP0:%.*]] = load <4 x ptr>, ptr @vec, align 32 16; CHECK-NEXT: [[DOTI0:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 0 17; CHECK-NEXT: [[DOTI01:%.*]] = getelementptr i16, ptr [[DOTI0]], i16 1 18; CHECK-NEXT: [[DOTI1:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 1 19; CHECK-NEXT: [[DOTI12:%.*]] = getelementptr i16, ptr [[DOTI1]], i16 1 20; CHECK-NEXT: [[DOTI2:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 2 21; CHECK-NEXT: [[DOTI23:%.*]] = getelementptr i16, ptr [[DOTI2]], i16 1 22; CHECK-NEXT: [[DOTI3:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 3 23; CHECK-NEXT: [[DOTI34:%.*]] = getelementptr i16, ptr [[DOTI3]], i16 1 24; CHECK-NEXT: ret void 25; 26bb: 27 %0 = load <4 x ptr>, ptr @vec 28 %1 = getelementptr i16, <4 x ptr> %0, i16 1 29 30 ret void 31} 32 33; non-constant index 34define void @test2() { 35; CHECK-LABEL: @test2( 36; CHECK-NEXT: bb: 37; CHECK-NEXT: [[TMP0:%.*]] = load <4 x ptr>, ptr @vec, align 32 38; CHECK-NEXT: [[DOTI0:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 0 39; CHECK-NEXT: [[DOTI1:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 1 40; CHECK-NEXT: [[DOTI2:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 2 41; CHECK-NEXT: [[DOTI3:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 3 42; CHECK-NEXT: [[INDEX:%.*]] = load i16, ptr @index, align 2 43; CHECK-NEXT: [[DOTI01:%.*]] = getelementptr i16, ptr [[DOTI0]], i16 [[INDEX]] 44; CHECK-NEXT: [[DOTI12:%.*]] = getelementptr i16, ptr [[DOTI1]], i16 [[INDEX]] 45; CHECK-NEXT: [[DOTI23:%.*]] = getelementptr i16, ptr [[DOTI2]], i16 [[INDEX]] 46; CHECK-NEXT: [[DOTI34:%.*]] = getelementptr i16, ptr [[DOTI3]], i16 [[INDEX]] 47; CHECK-NEXT: ret void 48; 49bb: 50 %0 = load <4 x ptr>, ptr @vec 51 %index = load i16, ptr @index 52 %1 = getelementptr i16, <4 x ptr> %0, i16 %index 53 54 ret void 55} 56 57; Check that the scalarizer can handle vector GEPs with scalar pointer 58 59; constant pointer 60define <4 x ptr> @test3_constexpr() { 61; CHECK-LABEL: @test3_constexpr( 62; CHECK-NEXT: bb: 63; CHECK-NEXT: ret <4 x ptr> getelementptr (i16, ptr @ptr, <4 x i64> <i64 0, i64 1, i64 2, i64 3>) 64; 65bb: 66 ret <4 x ptr> getelementptr (i16, ptr @ptr, <4 x i64> <i64 0, i64 1, i64 2, i64 3>) 67} 68 69 70define <4 x ptr> @test3_constbase(i16 %idx) { 71; CHECK-LABEL: @test3_constbase( 72; CHECK-NEXT: bb: 73; CHECK-NEXT: [[OFFSET:%.*]] = getelementptr [4 x i16], ptr @ptr, i16 0, i16 [[IDX:%.*]] 74; CHECK-NEXT: [[GEP_I0:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 0 75; CHECK-NEXT: [[GEP_I1:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 1 76; CHECK-NEXT: [[GEP_I2:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 2 77; CHECK-NEXT: [[GEP_I3:%.*]] = getelementptr i16, ptr [[OFFSET]], i16 3 78; CHECK-NEXT: [[GEP_UPTO0:%.*]] = insertelement <4 x ptr> poison, ptr [[GEP_I0]], i64 0 79; CHECK-NEXT: [[GEP_UPTO1:%.*]] = insertelement <4 x ptr> [[GEP_UPTO0]], ptr [[GEP_I1]], i64 1 80; CHECK-NEXT: [[GEP_UPTO2:%.*]] = insertelement <4 x ptr> [[GEP_UPTO1]], ptr [[GEP_I2]], i64 2 81; CHECK-NEXT: [[GEP:%.*]] = insertelement <4 x ptr> [[GEP_UPTO2]], ptr [[GEP_I3]], i64 3 82; CHECK-NEXT: ret <4 x ptr> [[GEP]] 83; 84bb: 85 %offset = getelementptr [4 x i16], ptr @ptr, i16 0, i16 %idx 86 %gep = getelementptr i16, ptr %offset, <4 x i16> <i16 0, i16 1, i16 2, i16 3> 87 ret <4 x ptr> %gep 88} 89 90; Constant pointer with a variable vector offset 91define <4 x ptr> @test3_varoffset(<4 x i16> %offset) { 92; CHECK-LABEL: @test3_varoffset( 93; CHECK-NEXT: bb: 94; CHECK-NEXT: [[OFFSET_I0:%.*]] = extractelement <4 x i16> [[OFFSET:%.*]], i64 0 95; CHECK-NEXT: [[GEP_I0:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I0]] 96; CHECK-NEXT: [[OFFSET_I1:%.*]] = extractelement <4 x i16> [[OFFSET]], i64 1 97; CHECK-NEXT: [[GEP_I1:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I1]] 98; CHECK-NEXT: [[OFFSET_I2:%.*]] = extractelement <4 x i16> [[OFFSET]], i64 2 99; CHECK-NEXT: [[GEP_I2:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I2]] 100; CHECK-NEXT: [[OFFSET_I3:%.*]] = extractelement <4 x i16> [[OFFSET]], i64 3 101; CHECK-NEXT: [[GEP_I3:%.*]] = getelementptr i16, ptr @ptr, i16 [[OFFSET_I3]] 102; CHECK-NEXT: [[GEP_UPTO0:%.*]] = insertelement <4 x ptr> poison, ptr [[GEP_I0]], i64 0 103; CHECK-NEXT: [[GEP_UPTO1:%.*]] = insertelement <4 x ptr> [[GEP_UPTO0]], ptr [[GEP_I1]], i64 1 104; CHECK-NEXT: [[GEP_UPTO2:%.*]] = insertelement <4 x ptr> [[GEP_UPTO1]], ptr [[GEP_I2]], i64 2 105; CHECK-NEXT: [[GEP:%.*]] = insertelement <4 x ptr> [[GEP_UPTO2]], ptr [[GEP_I3]], i64 3 106; CHECK-NEXT: ret <4 x ptr> [[GEP]] 107; 108bb: 109 %gep = getelementptr i16, ptr @ptr, <4 x i16> %offset 110 ret <4 x ptr> %gep 111} 112 113; non-constant pointer 114define void @test4() { 115; CHECK-LABEL: @test4( 116; CHECK-NEXT: bb: 117; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @ptrptr, align 8 118; CHECK-NEXT: [[DOTI0:%.*]] = getelementptr i16, ptr [[TMP0]], i16 0 119; CHECK-NEXT: [[DOTI1:%.*]] = getelementptr i16, ptr [[TMP0]], i16 1 120; CHECK-NEXT: [[DOTI2:%.*]] = getelementptr i16, ptr [[TMP0]], i16 2 121; CHECK-NEXT: [[DOTI3:%.*]] = getelementptr i16, ptr [[TMP0]], i16 3 122; CHECK-NEXT: ret void 123; 124bb: 125 %0 = load ptr, ptr @ptrptr 126 %1 = getelementptr i16, ptr %0, <4 x i16> <i16 0, i16 1, i16 2, i16 3> 127 128 ret void 129} 130 131; constant index, inbounds 132define void @test5() { 133; CHECK-LABEL: @test5( 134; CHECK-NEXT: bb: 135; CHECK-NEXT: [[TMP0:%.*]] = load <4 x ptr>, ptr @vec, align 32 136; CHECK-NEXT: [[DOTI0:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 0 137; CHECK-NEXT: [[DOTI01:%.*]] = getelementptr inbounds i16, ptr [[DOTI0]], i16 1 138; CHECK-NEXT: [[DOTI1:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 1 139; CHECK-NEXT: [[DOTI12:%.*]] = getelementptr inbounds i16, ptr [[DOTI1]], i16 1 140; CHECK-NEXT: [[DOTI2:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 2 141; CHECK-NEXT: [[DOTI23:%.*]] = getelementptr inbounds i16, ptr [[DOTI2]], i16 1 142; CHECK-NEXT: [[DOTI3:%.*]] = extractelement <4 x ptr> [[TMP0]], i64 3 143; CHECK-NEXT: [[DOTI34:%.*]] = getelementptr inbounds i16, ptr [[DOTI3]], i16 1 144; CHECK-NEXT: ret void 145; 146bb: 147 %0 = load <4 x ptr>, ptr @vec 148 %1 = getelementptr inbounds i16, <4 x ptr> %0, i16 1 149 150 ret void 151} 152 153