1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v \ 3; RUN: -riscv-v-vector-bits-min=-1 -riscv-v-slp-max-vf=0 -S | FileCheck %s --check-prefixes=CHECK 4; RUN: opt < %s -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v -S | FileCheck %s --check-prefixes=DEFAULT 5 6 7define void @simple_copy(ptr %dest, ptr %p) { 8; CHECK-LABEL: @simple_copy( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i16>, ptr [[P:%.*]], align 4 11; CHECK-NEXT: store <2 x i16> [[TMP0]], ptr [[DEST:%.*]], align 4 12; CHECK-NEXT: ret void 13; 14; DEFAULT-LABEL: @simple_copy( 15; DEFAULT-NEXT: entry: 16; DEFAULT-NEXT: [[TMP0:%.*]] = load <2 x i16>, ptr [[P:%.*]], align 4 17; DEFAULT-NEXT: store <2 x i16> [[TMP0]], ptr [[DEST:%.*]], align 4 18; DEFAULT-NEXT: ret void 19; 20entry: 21 %e0 = load i16, ptr %p, align 4 22 %inc = getelementptr inbounds i16, ptr %p, i64 1 23 %e1 = load i16, ptr %inc, align 2 24 25 store i16 %e0, ptr %dest, align 4 26 %inc2 = getelementptr inbounds i16, ptr %dest, i64 1 27 store i16 %e1, ptr %inc2, align 2 28 ret void 29} 30 31define void @vec_add(ptr %dest, ptr %p) { 32; CHECK-LABEL: @vec_add( 33; CHECK-NEXT: entry: 34; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i16>, ptr [[P:%.*]], align 4 35; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i16> [[TMP0]], splat (i16 1) 36; CHECK-NEXT: store <2 x i16> [[TMP1]], ptr [[DEST:%.*]], align 4 37; CHECK-NEXT: ret void 38; 39; DEFAULT-LABEL: @vec_add( 40; DEFAULT-NEXT: entry: 41; DEFAULT-NEXT: [[TMP0:%.*]] = load <2 x i16>, ptr [[P:%.*]], align 4 42; DEFAULT-NEXT: [[TMP1:%.*]] = add <2 x i16> [[TMP0]], splat (i16 1) 43; DEFAULT-NEXT: store <2 x i16> [[TMP1]], ptr [[DEST:%.*]], align 4 44; DEFAULT-NEXT: ret void 45; 46entry: 47 %e0 = load i16, ptr %p, align 4 48 %inc = getelementptr inbounds i16, ptr %p, i64 1 49 %e1 = load i16, ptr %inc, align 2 50 51 %a0 = add i16 %e0, 1 52 %a1 = add i16 %e1, 1 53 54 store i16 %a0, ptr %dest, align 4 55 %inc2 = getelementptr inbounds i16, ptr %dest, i64 1 56 store i16 %a1, ptr %inc2, align 2 57 ret void 58} 59 60 61define void @splat_store_i16(ptr %dest, ptr %p) { 62; CHECK-LABEL: @splat_store_i16( 63; CHECK-NEXT: entry: 64; CHECK-NEXT: [[E0:%.*]] = load i16, ptr [[P:%.*]], align 4 65; CHECK-NEXT: store i16 [[E0]], ptr [[DEST:%.*]], align 4 66; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i16, ptr [[DEST]], i64 1 67; CHECK-NEXT: store i16 [[E0]], ptr [[INC2]], align 2 68; CHECK-NEXT: ret void 69; 70; DEFAULT-LABEL: @splat_store_i16( 71; DEFAULT-NEXT: entry: 72; DEFAULT-NEXT: [[E0:%.*]] = load i16, ptr [[P:%.*]], align 4 73; DEFAULT-NEXT: store i16 [[E0]], ptr [[DEST:%.*]], align 4 74; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i16, ptr [[DEST]], i64 1 75; DEFAULT-NEXT: store i16 [[E0]], ptr [[INC2]], align 2 76; DEFAULT-NEXT: ret void 77; 78entry: 79 %e0 = load i16, ptr %p, align 4 80 81 store i16 %e0, ptr %dest, align 4 82 %inc2 = getelementptr inbounds i16, ptr %dest, i64 1 83 store i16 %e0, ptr %inc2, align 2 84 ret void 85} 86 87define void @splat_store_i64(ptr %dest, ptr %p) { 88; CHECK-LABEL: @splat_store_i64( 89; CHECK-NEXT: entry: 90; CHECK-NEXT: [[E0:%.*]] = load i64, ptr [[P:%.*]], align 4 91; CHECK-NEXT: store i64 [[E0]], ptr [[DEST:%.*]], align 4 92; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i64, ptr [[DEST]], i64 1 93; CHECK-NEXT: store i64 [[E0]], ptr [[INC2]], align 2 94; CHECK-NEXT: ret void 95; 96; DEFAULT-LABEL: @splat_store_i64( 97; DEFAULT-NEXT: entry: 98; DEFAULT-NEXT: [[E0:%.*]] = load i64, ptr [[P:%.*]], align 4 99; DEFAULT-NEXT: store i64 [[E0]], ptr [[DEST:%.*]], align 4 100; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i64, ptr [[DEST]], i64 1 101; DEFAULT-NEXT: store i64 [[E0]], ptr [[INC2]], align 2 102; DEFAULT-NEXT: ret void 103; 104entry: 105 %e0 = load i64, ptr %p, align 4 106 107 store i64 %e0, ptr %dest, align 4 108 %inc2 = getelementptr inbounds i64, ptr %dest, i64 1 109 store i64 %e0, ptr %inc2, align 2 110 ret void 111} 112 113define void @splat_store_i64_zero(ptr %dest) { 114; CHECK-LABEL: @splat_store_i64_zero( 115; CHECK-NEXT: entry: 116; CHECK-NEXT: store i64 0, ptr [[DEST:%.*]], align 4 117; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i64, ptr [[DEST]], i64 1 118; CHECK-NEXT: store i64 0, ptr [[INC2]], align 2 119; CHECK-NEXT: ret void 120; 121; DEFAULT-LABEL: @splat_store_i64_zero( 122; DEFAULT-NEXT: entry: 123; DEFAULT-NEXT: store i64 0, ptr [[DEST:%.*]], align 4 124; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i64, ptr [[DEST]], i64 1 125; DEFAULT-NEXT: store i64 0, ptr [[INC2]], align 2 126; DEFAULT-NEXT: ret void 127; 128entry: 129 store i64 0, ptr %dest, align 4 130 %inc2 = getelementptr inbounds i64, ptr %dest, i64 1 131 store i64 0, ptr %inc2, align 2 132 ret void 133} 134 135define void @splat_store_i64_one(ptr %dest) { 136; CHECK-LABEL: @splat_store_i64_one( 137; CHECK-NEXT: entry: 138; CHECK-NEXT: store i64 1, ptr [[DEST:%.*]], align 4 139; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i64, ptr [[DEST]], i64 1 140; CHECK-NEXT: store i64 1, ptr [[INC2]], align 2 141; CHECK-NEXT: ret void 142; 143; DEFAULT-LABEL: @splat_store_i64_one( 144; DEFAULT-NEXT: entry: 145; DEFAULT-NEXT: store i64 1, ptr [[DEST:%.*]], align 4 146; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i64, ptr [[DEST]], i64 1 147; DEFAULT-NEXT: store i64 1, ptr [[INC2]], align 2 148; DEFAULT-NEXT: ret void 149; 150entry: 151 store i64 1, ptr %dest, align 4 152 %inc2 = getelementptr inbounds i64, ptr %dest, i64 1 153 store i64 1, ptr %inc2, align 2 154 ret void 155} 156 157define void @splat_store_i32_zero(ptr %dest) { 158; CHECK-LABEL: @splat_store_i32_zero( 159; CHECK-NEXT: entry: 160; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr [[DEST:%.*]], align 4 161; CHECK-NEXT: ret void 162; 163; DEFAULT-LABEL: @splat_store_i32_zero( 164; DEFAULT-NEXT: entry: 165; DEFAULT-NEXT: store <4 x i32> zeroinitializer, ptr [[DEST:%.*]], align 4 166; DEFAULT-NEXT: ret void 167; 168entry: 169 store i32 0, ptr %dest, align 4 170 %inc1 = getelementptr inbounds i32, ptr %dest, i64 1 171 store i32 0, ptr %inc1, align 2 172 %inc2 = getelementptr inbounds i32, ptr %dest, i64 2 173 store i32 0, ptr %inc2, align 2 174 %inc3 = getelementptr inbounds i32, ptr %dest, i64 3 175 store i32 0, ptr %inc3, align 2 176 ret void 177} 178 179define void @splat_store_i32_one(ptr %dest) { 180; CHECK-LABEL: @splat_store_i32_one( 181; CHECK-NEXT: entry: 182; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[DEST:%.*]], align 4 183; CHECK-NEXT: ret void 184; 185; DEFAULT-LABEL: @splat_store_i32_one( 186; DEFAULT-NEXT: entry: 187; DEFAULT-NEXT: store <4 x i32> splat (i32 1), ptr [[DEST:%.*]], align 4 188; DEFAULT-NEXT: ret void 189; 190entry: 191 store i32 1, ptr %dest, align 4 192 %inc1 = getelementptr inbounds i32, ptr %dest, i64 1 193 store i32 1, ptr %inc1, align 2 194 %inc2 = getelementptr inbounds i32, ptr %dest, i64 2 195 store i32 1, ptr %inc2, align 2 196 %inc3 = getelementptr inbounds i32, ptr %dest, i64 3 197 store i32 1, ptr %inc3, align 2 198 ret void 199} 200 201define void @store_stepvector_i32(ptr %dest) { 202; CHECK-LABEL: @store_stepvector_i32( 203; CHECK-NEXT: entry: 204; CHECK-NEXT: store i32 0, ptr [[DEST:%.*]], align 4 205; CHECK-NEXT: [[INC1:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 1 206; CHECK-NEXT: store i32 1, ptr [[INC1]], align 2 207; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 2 208; CHECK-NEXT: store i32 2, ptr [[INC2]], align 2 209; CHECK-NEXT: [[INC3:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 3 210; CHECK-NEXT: store i32 3, ptr [[INC3]], align 2 211; CHECK-NEXT: ret void 212; 213; DEFAULT-LABEL: @store_stepvector_i32( 214; DEFAULT-NEXT: entry: 215; DEFAULT-NEXT: store i32 0, ptr [[DEST:%.*]], align 4 216; DEFAULT-NEXT: [[INC1:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 1 217; DEFAULT-NEXT: store i32 1, ptr [[INC1]], align 2 218; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 2 219; DEFAULT-NEXT: store i32 2, ptr [[INC2]], align 2 220; DEFAULT-NEXT: [[INC3:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 3 221; DEFAULT-NEXT: store i32 3, ptr [[INC3]], align 2 222; DEFAULT-NEXT: ret void 223; 224entry: 225 store i32 0, ptr %dest, align 4 226 %inc1 = getelementptr inbounds i32, ptr %dest, i64 1 227 store i32 1, ptr %inc1, align 2 228 %inc2 = getelementptr inbounds i32, ptr %dest, i64 2 229 store i32 2, ptr %inc2, align 2 230 %inc3 = getelementptr inbounds i32, ptr %dest, i64 3 231 store i32 3, ptr %inc3, align 2 232 ret void 233} 234 235define void @store_arbitrary_constant_i32(ptr %dest) { 236; CHECK-LABEL: @store_arbitrary_constant_i32( 237; CHECK-NEXT: entry: 238; CHECK-NEXT: store i32 0, ptr [[DEST:%.*]], align 4 239; CHECK-NEXT: [[INC1:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 1 240; CHECK-NEXT: store i32 -33, ptr [[INC1]], align 2 241; CHECK-NEXT: [[INC2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 2 242; CHECK-NEXT: store i32 44, ptr [[INC2]], align 2 243; CHECK-NEXT: [[INC3:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 3 244; CHECK-NEXT: store i32 77, ptr [[INC3]], align 2 245; CHECK-NEXT: ret void 246; 247; DEFAULT-LABEL: @store_arbitrary_constant_i32( 248; DEFAULT-NEXT: entry: 249; DEFAULT-NEXT: store i32 0, ptr [[DEST:%.*]], align 4 250; DEFAULT-NEXT: [[INC1:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 1 251; DEFAULT-NEXT: store i32 -33, ptr [[INC1]], align 2 252; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 2 253; DEFAULT-NEXT: store i32 44, ptr [[INC2]], align 2 254; DEFAULT-NEXT: [[INC3:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 3 255; DEFAULT-NEXT: store i32 77, ptr [[INC3]], align 2 256; DEFAULT-NEXT: ret void 257; 258entry: 259 store i32 0, ptr %dest, align 4 260 %inc1 = getelementptr inbounds i32, ptr %dest, i64 1 261 store i32 -33, ptr %inc1, align 2 262 %inc2 = getelementptr inbounds i32, ptr %dest, i64 2 263 store i32 44, ptr %inc2, align 2 264 %inc3 = getelementptr inbounds i32, ptr %dest, i64 3 265 store i32 77, ptr %inc3, align 2 266 ret void 267} 268