1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -aa-pipeline='basic-aa,scoped-noalias-aa' -passes=slp-vectorizer -mtriple=arm64-apple-darwin -S %s | FileCheck %s 3 4define void @needs_versioning_not_profitable(ptr %dst, ptr %src) { 5; CHECK-LABEL: @needs_versioning_not_profitable( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 8; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 9; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 10; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 11; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 12; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 13; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 14; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 15; CHECK-NEXT: ret void 16; 17entry: 18 %src.0 = load i32, ptr %src, align 4 19 %r.0 = ashr i32 %src.0, 16 20 store i32 %r.0, ptr %dst, align 4 21 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 22 %src.1 = load i32, ptr %src.gep.1, align 4 23 %r.1 = ashr i32 %src.1, 16 24 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 25 store i32 %r.1, ptr %dst.gep.1, align 4 26 ret void 27} 28 29define void @needs_versioning_profitable(ptr %dst, ptr %src) { 30; CHECK-LABEL: @needs_versioning_profitable( 31; CHECK-NEXT: entry: 32; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 33; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 34; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 35; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 36; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 37; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 38; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 39; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 40; CHECK-NEXT: [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2 41; CHECK-NEXT: [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4 42; CHECK-NEXT: [[R_2:%.*]] = ashr i32 [[SRC_2]], 16 43; CHECK-NEXT: [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2 44; CHECK-NEXT: store i32 [[R_2]], ptr [[DST_GEP_2]], align 4 45; CHECK-NEXT: [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3 46; CHECK-NEXT: [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4 47; CHECK-NEXT: [[R_3:%.*]] = ashr i32 [[SRC_3]], 16 48; CHECK-NEXT: [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3 49; CHECK-NEXT: store i32 [[R_3]], ptr [[DST_GEP_3]], align 4 50; CHECK-NEXT: ret void 51; 52entry: 53 %src.0 = load i32, ptr %src, align 4 54 %r.0 = ashr i32 %src.0, 16 55 store i32 %r.0, ptr %dst, align 4 56 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 57 %src.1 = load i32, ptr %src.gep.1, align 4 58 %r.1 = ashr i32 %src.1, 16 59 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 60 store i32 %r.1, ptr %dst.gep.1, align 4 61 %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2 62 %src.2 = load i32, ptr %src.gep.2, align 4 63 %r.2 = ashr i32 %src.2, 16 64 %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2 65 store i32 %r.2, ptr %dst.gep.2, align 4 66 %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3 67 %src.3 = load i32, ptr %src.gep.3, align 4 68 %r.3 = ashr i32 %src.3, 16 69 %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3 70 store i32 %r.3, ptr %dst.gep.3, align 4 71 72 ret void 73} 74 75define void @needs_versioning_profitable_2_sources(ptr %dst, ptr %A, ptr %B) { 76; CHECK-LABEL: @needs_versioning_profitable_2_sources( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[A_0:%.*]] = load i32, ptr [[A:%.*]], align 4 79; CHECK-NEXT: [[B_0:%.*]] = load i32, ptr [[B:%.*]], align 4 80; CHECK-NEXT: [[R_0:%.*]] = add i32 [[A_0]], [[B_0]] 81; CHECK-NEXT: [[MUL_0:%.*]] = mul i32 [[R_0]], 2 82; CHECK-NEXT: store i32 [[MUL_0]], ptr [[DST:%.*]], align 4 83; CHECK-NEXT: [[A_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 1 84; CHECK-NEXT: [[A_1:%.*]] = load i32, ptr [[A_GEP_1]], align 4 85; CHECK-NEXT: [[B_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 1 86; CHECK-NEXT: [[B_1:%.*]] = load i32, ptr [[B_GEP_1]], align 4 87; CHECK-NEXT: [[R_1:%.*]] = add i32 [[A_1]], [[B_1]] 88; CHECK-NEXT: [[MUL_1:%.*]] = mul i32 [[R_1]], 2 89; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 90; CHECK-NEXT: store i32 [[MUL_1]], ptr [[DST_GEP_1]], align 4 91; CHECK-NEXT: [[A_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 2 92; CHECK-NEXT: [[A_2:%.*]] = load i32, ptr [[A_GEP_2]], align 4 93; CHECK-NEXT: [[B_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 2 94; CHECK-NEXT: [[B_2:%.*]] = load i32, ptr [[B_GEP_2]], align 4 95; CHECK-NEXT: [[R_2:%.*]] = add i32 [[A_2]], [[B_2]] 96; CHECK-NEXT: [[MUL_2:%.*]] = mul i32 [[R_2]], 2 97; CHECK-NEXT: [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2 98; CHECK-NEXT: store i32 [[MUL_2]], ptr [[DST_GEP_2]], align 4 99; CHECK-NEXT: [[A_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 3 100; CHECK-NEXT: [[A_3:%.*]] = load i32, ptr [[A_GEP_3]], align 4 101; CHECK-NEXT: [[B_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 3 102; CHECK-NEXT: [[B_3:%.*]] = load i32, ptr [[B_GEP_3]], align 4 103; CHECK-NEXT: [[R_3:%.*]] = add i32 [[A_3]], [[B_3]] 104; CHECK-NEXT: [[MUL_3:%.*]] = mul i32 [[R_3]], 2 105; CHECK-NEXT: [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3 106; CHECK-NEXT: store i32 [[MUL_3]], ptr [[DST_GEP_3]], align 4 107; CHECK-NEXT: ret void 108; 109entry: 110 %A.0 = load i32, ptr %A, align 4 111 %B.0 = load i32, ptr %B, align 4 112 %r.0 = add i32 %A.0, %B.0 113 %mul.0 = mul i32 %r.0, 2 114 store i32 %mul.0, ptr %dst, align 4 115 %A.gep.1 = getelementptr inbounds i32, ptr %A, i64 1 116 %A.1 = load i32, ptr %A.gep.1, align 4 117 %B.gep.1 = getelementptr inbounds i32, ptr %B, i64 1 118 %B.1 = load i32, ptr %B.gep.1, align 4 119 %r.1 = add i32 %A.1, %B.1 120 %mul.1 = mul i32 %r.1, 2 121 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 122 store i32 %mul.1, ptr %dst.gep.1, align 4 123 %A.gep.2 = getelementptr inbounds i32, ptr %A, i64 2 124 %A.2 = load i32, ptr %A.gep.2, align 4 125 %B.gep.2 = getelementptr inbounds i32, ptr %B, i64 2 126 %B.2 = load i32, ptr %B.gep.2, align 4 127 %r.2 = add i32 %A.2, %B.2 128 %mul.2 = mul i32 %r.2, 2 129 %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2 130 store i32 %mul.2, ptr %dst.gep.2, align 4 131 %A.gep.3 = getelementptr inbounds i32, ptr %A, i64 3 132 %A.3 = load i32, ptr %A.gep.3, align 4 133 %B.gep.3 = getelementptr inbounds i32, ptr %B, i64 3 134 %B.3 = load i32, ptr %B.gep.3, align 4 135 %r.3 = add i32 %A.3, %B.3 136 %mul.3 = mul i32 %r.3, 2 137 %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3 138 store i32 %mul.3, ptr %dst.gep.3, align 4 139 140 ret void 141} 142 143declare void @use(i32) 144 145declare void @bar() 146 147define void @needs_versioning_profitable_split_points(ptr %dst, ptr %src) { 148; CHECK-LABEL: @needs_versioning_profitable_split_points( 149; CHECK-NEXT: entry: 150; CHECK-NEXT: call void @bar() 151; CHECK-NEXT: call void @bar() 152; CHECK-NEXT: call void @bar() 153; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 154; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 155; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 156; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 157; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 158; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 159; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 160; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 161; CHECK-NEXT: [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2 162; CHECK-NEXT: [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4 163; CHECK-NEXT: [[R_2:%.*]] = ashr i32 [[SRC_2]], 16 164; CHECK-NEXT: [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2 165; CHECK-NEXT: store i32 [[R_2]], ptr [[DST_GEP_2]], align 4 166; CHECK-NEXT: [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3 167; CHECK-NEXT: [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4 168; CHECK-NEXT: [[R_3:%.*]] = ashr i32 [[SRC_3]], 16 169; CHECK-NEXT: [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3 170; CHECK-NEXT: store i32 [[R_3]], ptr [[DST_GEP_3]], align 4 171; CHECK-NEXT: call void @bar() 172; CHECK-NEXT: ret void 173; 174entry: 175 call void @bar() 176 call void @bar() 177 call void @bar() 178 179 %src.0 = load i32, ptr %src, align 4 180 %r.0 = ashr i32 %src.0, 16 181 store i32 %r.0, ptr %dst, align 4 182 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 183 %src.1 = load i32, ptr %src.gep.1, align 4 184 %r.1 = ashr i32 %src.1, 16 185 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 186 store i32 %r.1, ptr %dst.gep.1, align 4 187 %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2 188 %src.2 = load i32, ptr %src.gep.2, align 4 189 %r.2 = ashr i32 %src.2, 16 190 %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2 191 store i32 %r.2, ptr %dst.gep.2, align 4 192 %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3 193 %src.3 = load i32, ptr %src.gep.3, align 4 194 %r.3 = ashr i32 %src.3, 16 195 %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3 196 store i32 %r.3, ptr %dst.gep.3, align 4 197 198 call void @bar() 199 ret void 200} 201 202define void @needs_versioning_profitable_load_used_outside_region1(ptr %dst, ptr %src, i1 %c) { 203; CHECK-LABEL: @needs_versioning_profitable_load_used_outside_region1( 204; CHECK-NEXT: entry: 205; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 206; CHECK: then: 207; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 208; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 209; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 210; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 211; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 212; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 213; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 214; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 215; CHECK-NEXT: [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2 216; CHECK-NEXT: [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4 217; CHECK-NEXT: [[R_2:%.*]] = ashr i32 [[SRC_2]], 16 218; CHECK-NEXT: [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2 219; CHECK-NEXT: store i32 [[R_2]], ptr [[DST_GEP_2]], align 4 220; CHECK-NEXT: [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3 221; CHECK-NEXT: [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4 222; CHECK-NEXT: [[R_3:%.*]] = ashr i32 [[SRC_3]], 16 223; CHECK-NEXT: [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3 224; CHECK-NEXT: store i32 [[R_3]], ptr [[DST_GEP_3]], align 4 225; CHECK-NEXT: [[SRC_GEP_5:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 5 226; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SRC_GEP_5]], align 4 227; CHECK-NEXT: call void @use(i32 [[L]]) 228; CHECK-NEXT: br label [[EXIT]] 229; CHECK: exit: 230; CHECK-NEXT: ret void 231; 232entry: 233 br i1 %c, label %then, label %exit 234 235then: 236 %src.0 = load i32, ptr %src, align 4 237 %r.0 = ashr i32 %src.0, 16 238 store i32 %r.0, ptr %dst, align 4 239 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 240 %src.1 = load i32, ptr %src.gep.1, align 4 241 %r.1 = ashr i32 %src.1, 16 242 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 243 store i32 %r.1, ptr %dst.gep.1, align 4 244 %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2 245 %src.2 = load i32, ptr %src.gep.2, align 4 246 %r.2 = ashr i32 %src.2, 16 247 %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2 248 store i32 %r.2, ptr %dst.gep.2, align 4 249 %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3 250 %src.3 = load i32, ptr %src.gep.3, align 4 251 %r.3 = ashr i32 %src.3, 16 252 %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3 253 store i32 %r.3, ptr %dst.gep.3, align 4 254 %src.gep.5 = getelementptr inbounds i32, ptr %src, i64 5 255 %l = load i32, ptr %src.gep.5 256 call void @use(i32 %l) 257 br label %exit 258 259exit: 260 ret void 261} 262 263define void @needs_versioning_profitable_load_used_outside_region2(ptr %dst, ptr %src, i1 %c) { 264; CHECK-LABEL: @needs_versioning_profitable_load_used_outside_region2( 265; CHECK-NEXT: entry: 266; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 267; CHECK: then: 268; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 269; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 270; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 271; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 272; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 273; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 274; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 275; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 276; CHECK-NEXT: [[SRC_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2 277; CHECK-NEXT: [[SRC_2:%.*]] = load i32, ptr [[SRC_GEP_2]], align 4 278; CHECK-NEXT: [[SRC_GEP_5:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 5 279; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SRC_GEP_5]], align 4 280; CHECK-NEXT: [[R_2:%.*]] = ashr i32 [[SRC_2]], 16 281; CHECK-NEXT: [[DST_GEP_2:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2 282; CHECK-NEXT: store i32 [[R_2]], ptr [[DST_GEP_2]], align 4 283; CHECK-NEXT: [[SRC_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3 284; CHECK-NEXT: [[SRC_3:%.*]] = load i32, ptr [[SRC_GEP_3]], align 4 285; CHECK-NEXT: [[R_3:%.*]] = ashr i32 [[SRC_3]], 16 286; CHECK-NEXT: [[DST_GEP_3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3 287; CHECK-NEXT: store i32 [[R_3]], ptr [[DST_GEP_3]], align 4 288; CHECK-NEXT: call void @use(i32 [[L]]) 289; CHECK-NEXT: br label [[EXIT]] 290; CHECK: exit: 291; CHECK-NEXT: ret void 292; 293entry: 294 br i1 %c, label %then, label %exit 295 296then: 297 %src.0 = load i32, ptr %src, align 4 298 %r.0 = ashr i32 %src.0, 16 299 store i32 %r.0, ptr %dst, align 4 300 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 301 %src.1 = load i32, ptr %src.gep.1, align 4 302 %r.1 = ashr i32 %src.1, 16 303 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 304 store i32 %r.1, ptr %dst.gep.1, align 4 305 %src.gep.2 = getelementptr inbounds i32, ptr %src, i64 2 306 %src.2 = load i32, ptr %src.gep.2, align 4 307 %src.gep.5 = getelementptr inbounds i32, ptr %src, i64 5 308 %l = load i32, ptr %src.gep.5 309 %r.2 = ashr i32 %src.2, 16 310 %dst.gep.2 = getelementptr inbounds i32, ptr %dst, i64 2 311 store i32 %r.2, ptr %dst.gep.2, align 4 312 %src.gep.3 = getelementptr inbounds i32, ptr %src, i64 3 313 %src.3 = load i32, ptr %src.gep.3, align 4 314 %r.3 = ashr i32 %src.3, 16 315 %dst.gep.3 = getelementptr inbounds i32, ptr %dst, i64 3 316 store i32 %r.3, ptr %dst.gep.3, align 4 317 call void @use(i32 %l) 318 br label %exit 319 320exit: 321 ret void 322} 323 324define void @no_version(ptr nocapture %dst, ptr nocapture readonly %src) { 325; CHECK-LABEL: @no_version( 326; CHECK-NEXT: entry: 327; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[SRC:%.*]], align 4 328; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> [[TMP0]], splat (i32 16) 329; CHECK-NEXT: store <2 x i32> [[TMP1]], ptr [[DST:%.*]], align 4 330; CHECK-NEXT: ret void 331; 332entry: 333 %src.0 = load i32, ptr %src, align 4 334 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 335 %src.1 = load i32, ptr %src.gep.1, align 4 336 %r.0 = ashr i32 %src.0, 16 337 %r.1 = ashr i32 %src.1, 16 338 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 339 store i32 %r.0, ptr %dst, align 4 340 store i32 %r.1, ptr %dst.gep.1, align 4 341 ret void 342} 343 344define void @version_multiple(ptr nocapture %out_block, ptr nocapture readonly %counter) { 345; CHECK-LABEL: @version_multiple( 346; CHECK-NEXT: entry: 347; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNTER:%.*]], align 4 348; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[OUT_BLOCK:%.*]], align 4 349; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], [[TMP0]] 350; CHECK-NEXT: store i32 [[XOR]], ptr [[OUT_BLOCK]], align 4 351; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds i32, ptr [[COUNTER]], i64 1 352; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX_1]], align 4 353; CHECK-NEXT: [[ARRAYIDX2_1:%.*]] = getelementptr inbounds i32, ptr [[OUT_BLOCK]], i64 1 354; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX2_1]], align 4 355; CHECK-NEXT: [[XOR_1:%.*]] = xor i32 [[TMP3]], [[TMP2]] 356; CHECK-NEXT: store i32 [[XOR_1]], ptr [[ARRAYIDX2_1]], align 4 357; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds i32, ptr [[COUNTER]], i64 2 358; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX_2]], align 4 359; CHECK-NEXT: [[ARRAYIDX2_2:%.*]] = getelementptr inbounds i32, ptr [[OUT_BLOCK]], i64 2 360; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX2_2]], align 4 361; CHECK-NEXT: [[XOR_2:%.*]] = xor i32 [[TMP5]], [[TMP4]] 362; CHECK-NEXT: store i32 [[XOR_2]], ptr [[ARRAYIDX2_2]], align 4 363; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds i32, ptr [[COUNTER]], i64 3 364; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX_3]], align 4 365; CHECK-NEXT: [[ARRAYIDX2_3:%.*]] = getelementptr inbounds i32, ptr [[OUT_BLOCK]], i64 3 366; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ARRAYIDX2_3]], align 4 367; CHECK-NEXT: [[XOR_3:%.*]] = xor i32 [[TMP7]], [[TMP6]] 368; CHECK-NEXT: store i32 [[XOR_3]], ptr [[ARRAYIDX2_3]], align 4 369; CHECK-NEXT: ret void 370; 371entry: 372 %0 = load i32, ptr %counter, align 4 373 %1 = load i32, ptr %out_block, align 4 374 %xor = xor i32 %1, %0 375 store i32 %xor, ptr %out_block, align 4 376 %arrayidx.1 = getelementptr inbounds i32, ptr %counter, i64 1 377 %2 = load i32, ptr %arrayidx.1, align 4 378 %arrayidx2.1 = getelementptr inbounds i32, ptr %out_block, i64 1 379 %3 = load i32, ptr %arrayidx2.1, align 4 380 %xor.1 = xor i32 %3, %2 381 store i32 %xor.1, ptr %arrayidx2.1, align 4 382 %arrayidx.2 = getelementptr inbounds i32, ptr %counter, i64 2 383 %4 = load i32, ptr %arrayidx.2, align 4 384 %arrayidx2.2 = getelementptr inbounds i32, ptr %out_block, i64 2 385 %5 = load i32, ptr %arrayidx2.2, align 4 386 %xor.2 = xor i32 %5, %4 387 store i32 %xor.2, ptr %arrayidx2.2, align 4 388 %arrayidx.3 = getelementptr inbounds i32, ptr %counter, i64 3 389 %6 = load i32, ptr %arrayidx.3, align 4 390 %arrayidx2.3 = getelementptr inbounds i32, ptr %out_block, i64 3 391 %7 = load i32, ptr %arrayidx2.3, align 4 392 %xor.3 = xor i32 %7, %6 393 store i32 %xor.3, ptr %arrayidx2.3, align 4 394 ret void 395} 396 397define i32 @use_outside_version_bb(ptr %dst, ptr %src, i1 %c.1) { 398; CHECK-LABEL: @use_outside_version_bb( 399; CHECK-NEXT: entry: 400; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 401; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 402; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 403; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 404; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 405; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 406; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 407; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 408; CHECK-NEXT: br label [[EXIT:%.*]] 409; CHECK: exit: 410; CHECK-NEXT: ret i32 [[R_0]] 411; 412entry: 413 %src.0 = load i32, ptr %src, align 4 414 %r.0 = ashr i32 %src.0, 16 415 store i32 %r.0, ptr %dst, align 4 416 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 417 %src.1 = load i32, ptr %src.gep.1, align 4 418 %r.1 = ashr i32 %src.1, 16 419 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 420 store i32 %r.1, ptr %dst.gep.1, align 4 421 br label %exit 422 423exit: 424 ret i32 %r.0 425} 426 427define i32 @value_used_in_return(ptr %dst, ptr %src, i32 %x) { 428; CHECK-LABEL: @value_used_in_return( 429; CHECK-NEXT: entry: 430; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 431; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 432; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 433; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 434; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 435; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 436; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 437; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 438; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X:%.*]], 20 439; CHECK-NEXT: ret i32 [[ADD]] 440; 441entry: 442 %src.0 = load i32, ptr %src, align 4 443 %r.0 = ashr i32 %src.0, 16 444 store i32 %r.0, ptr %dst, align 4 445 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 446 %src.1 = load i32, ptr %src.gep.1, align 4 447 %r.1 = ashr i32 %src.1, 16 448 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 449 store i32 %r.1, ptr %dst.gep.1, align 4 450 %add = add i32 %x, 20 451 ret i32 %add 452} 453define i32 @needs_versioning2_cond_br(ptr %dst, ptr %src, i1 %c.1) { 454; CHECK-LABEL: @needs_versioning2_cond_br( 455; CHECK-NEXT: entry: 456; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 457; CHECK: then: 458; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC:%.*]], align 4 459; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 460; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 461; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 462; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 463; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 464; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 465; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 466; CHECK-NEXT: ret i32 10 467; CHECK: else: 468; CHECK-NEXT: ret i32 0 469; 470entry: 471 br i1 %c.1, label %then, label %else 472 473then: 474 %src.0 = load i32, ptr %src, align 4 475 %r.0 = ashr i32 %src.0, 16 476 store i32 %r.0, ptr %dst, align 4 477 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 478 %src.1 = load i32, ptr %src.gep.1, align 4 479 %r.1 = ashr i32 %src.1, 16 480 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 481 store i32 %r.1, ptr %dst.gep.1, align 4 482 ret i32 10 483 484 485else: 486 ret i32 0 487} 488 489define void @pointer_defined_in_bb(ptr %dst, ptr %src.p) { 490; CHECK-LABEL: @pointer_defined_in_bb( 491; CHECK-NEXT: entry: 492; CHECK-NEXT: [[SRC:%.*]] = load ptr, ptr [[SRC_P:%.*]], align 8 493; CHECK-NEXT: [[SRC_0:%.*]] = load i32, ptr [[SRC]], align 4 494; CHECK-NEXT: [[R_0:%.*]] = ashr i32 [[SRC_0]], 16 495; CHECK-NEXT: store i32 [[R_0]], ptr [[DST:%.*]], align 4 496; CHECK-NEXT: [[SRC_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1 497; CHECK-NEXT: [[SRC_1:%.*]] = load i32, ptr [[SRC_GEP_1]], align 4 498; CHECK-NEXT: [[R_1:%.*]] = ashr i32 [[SRC_1]], 16 499; CHECK-NEXT: [[DST_GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 1 500; CHECK-NEXT: store i32 [[R_1]], ptr [[DST_GEP_1]], align 4 501; CHECK-NEXT: ret void 502; 503entry: 504 %src = load ptr, ptr %src.p 505 %src.0 = load i32, ptr %src, align 4 506 %r.0 = ashr i32 %src.0, 16 507 store i32 %r.0, ptr %dst, align 4 508 %src.gep.1 = getelementptr inbounds i32, ptr %src, i64 1 509 %src.1 = load i32, ptr %src.gep.1, align 4 510 %r.1 = ashr i32 %src.1, 16 511 %dst.gep.1 = getelementptr inbounds i32, ptr %dst, i64 1 512 store i32 %r.1, ptr %dst.gep.1, align 4 513 ret void 514} 515 516define void @clobber_same_underlying_object(ptr %this) { 517; CHECK-LABEL: @clobber_same_underlying_object( 518; CHECK-NEXT: entry: 519; CHECK-NEXT: [[P_3:%.*]] = getelementptr inbounds i32, ptr [[THIS:%.*]], i32 3 520; CHECK-NEXT: store i32 10, ptr [[P_3]], align 8 521; CHECK-NEXT: tail call void @clobber() 522; CHECK-NEXT: [[P_4:%.*]] = getelementptr inbounds i32, ptr [[THIS]], i32 4 523; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[P_4]], align 8 524; CHECK-NEXT: store i32 20, ptr [[P_4]], align 8 525; CHECK-NEXT: ret void 526; 527entry: 528 %p.3 = getelementptr inbounds i32, ptr %this, i32 3 529 store i32 10, ptr %p.3, align 8 530 tail call void @clobber() 531 %p.4 = getelementptr inbounds i32, ptr %this, i32 4 532 %l2 = load i32, ptr %p.4, align 8 533 store i32 20, ptr %p.4, align 8 534 ret void 535} 536 537declare void @clobber() 538 539define void @slp_not_beneficial(ptr %A, ptr %B) { 540; CHECK-LABEL: @slp_not_beneficial( 541; CHECK-NEXT: bb: 542; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 4 543; CHECK-NEXT: store i32 0, ptr [[TMP]], align 8 544; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 5 545; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i32 4 546; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 8 547; CHECK-NEXT: store i32 [[TMP5]], ptr [[TMP3]], align 8 548; CHECK-NEXT: ret void 549; 550bb: 551 %tmp = getelementptr inbounds i32, ptr %A, i32 4 552 store i32 0, ptr %tmp, align 8 553 %tmp3 = getelementptr inbounds i32, ptr %A, i32 5 554 %tmp4 = getelementptr inbounds i32, ptr %B, i32 4 555 %tmp5 = load i32, ptr %tmp4, align 8 556 store i32 %tmp5, ptr %tmp3, align 8 557 ret void 558} 559 560define void @widget(ptr %ptr, ptr %ptr.2) { 561; CHECK-LABEL: @widget( 562; CHECK-NEXT: bb1: 563; CHECK-NEXT: [[TMP3:%.*]] = load double, ptr null, align 8 564; CHECK-NEXT: [[TMP4:%.*]] = fmul double undef, [[TMP3]] 565; CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[PTR:%.*]], align 8 566; CHECK-NEXT: [[TMP7:%.*]] = fadd double [[TMP6]], [[TMP4]] 567; CHECK-NEXT: store double [[TMP7]], ptr [[PTR]], align 8 568; CHECK-NEXT: [[TMP9:%.*]] = load double, ptr [[PTR_2:%.*]], align 8 569; CHECK-NEXT: [[TMP10:%.*]] = fmul double undef, [[TMP9]] 570; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds double, ptr [[PTR]], i32 1 571; CHECK-NEXT: [[TMP12:%.*]] = load double, ptr [[TMP11]], align 8 572; CHECK-NEXT: [[TMP13:%.*]] = fadd double [[TMP12]], [[TMP10]] 573; CHECK-NEXT: store double [[TMP13]], ptr [[TMP11]], align 8 574; CHECK-NEXT: br label [[BB15:%.*]] 575; CHECK: bb15: 576; CHECK-NEXT: br label [[BB15]] 577; 578bb1: ; preds = %bb 579 %tmp3 = load double, ptr null, align 8 580 %tmp4 = fmul double undef, %tmp3 581 %tmp6 = load double, ptr %ptr, align 8 582 %tmp7 = fadd double %tmp6, %tmp4 583 store double %tmp7, ptr %ptr, align 8 584 %tmp9 = load double, ptr %ptr.2, align 8 585 %tmp10 = fmul double undef, %tmp9 586 %tmp11 = getelementptr inbounds double, ptr %ptr, i32 1 587 %tmp12 = load double, ptr %tmp11, align 8 588 %tmp13 = fadd double %tmp12, %tmp10 589 store double %tmp13, ptr %tmp11, align 8 590 br label %bb15 591 592bb15: ; preds = %bb15, %bb14 593 br label %bb15 594} 595 596%struct = type { i32, i32, float, float } 597 598; Some points we collected as candidates for runtime checks have been removed 599; before generating runtime checks. Make sure versioning is skipped. 600define void @test_bounds_removed_before_runtime_checks(ptr %A, ptr %B, i1 %c) { 601; CHECK-LABEL: @test_bounds_removed_before_runtime_checks( 602; CHECK-NEXT: entry: 603; CHECK-NEXT: store <2 x i32> <i32 10, i32 300>, ptr [[A:%.*]], align 8 604; CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[B:%.*]], align 8 605; CHECK-NEXT: br i1 [[C:%.*]], label [[BB23:%.*]], label [[BB14:%.*]] 606; CHECK: bb14: 607; CHECK-NEXT: [[TMP15:%.*]] = sext i32 10 to i64 608; CHECK-NEXT: [[TMP16:%.*]] = add nsw i64 2, [[TMP15]] 609; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 [[TMP16]] 610; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 3 611; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT:%.*]], ptr [[A]], i64 0, i32 2 612; CHECK-NEXT: store float 0.000000e+00, ptr [[TMP20]], align 8 613; CHECK-NEXT: [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1 614; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT]], ptr [[A]], i64 0, i32 3 615; CHECK-NEXT: store float 0.000000e+00, ptr [[TMP22]], align 4 616; CHECK-NEXT: br label [[BB23]] 617; CHECK: bb23: 618; CHECK-NEXT: ret void 619; 620entry: 621 %tmp1 = fmul float 10.0, 20.0 622 %tmp2 = fptosi float %tmp1 to i32 623 %tmp3 = fmul float 30.0, 20.0 624 %tmp4 = fptosi float %tmp3 to i32 625 %tmp5 = icmp sgt i32 100, %tmp2 626 %tmp6 = select i1 %tmp5, i32 %tmp2, i32 10 627 %tmp7 = select i1 false, i32 0, i32 %tmp6 628 %tmp8 = icmp sgt i32 200, %tmp4 629 %tmp9 = select i1 %tmp8, i32 %tmp4, i32 300 630 %tmp10 = select i1 false, i32 0, i32 %tmp9 631 store i32 %tmp7, ptr %A, align 8 632 %tmp12 = getelementptr inbounds %struct, ptr %A, i64 0, i32 1 633 store i32 %tmp10, ptr %tmp12, align 4 634 %tmp13 = load ptr, ptr %B, align 8 635 br i1 %c, label %bb23, label %bb14 636 637bb14: 638 %tmp15 = sext i32 %tmp7 to i64 639 %tmp16 = add nsw i64 2, %tmp15 640 %tmp17 = getelementptr inbounds i32, ptr %tmp13, i64 %tmp16 641 %tmp19 = getelementptr inbounds i8, ptr %tmp17, i64 3 642 %tmp20 = getelementptr inbounds %struct, ptr %A, i64 0, i32 2 643 store float 0.0, ptr %tmp20, align 8 644 %tmp21 = load i8, ptr %tmp19, align 1 645 %tmp22 = getelementptr inbounds %struct, ptr %A, i64 0, i32 3 646 store float 0.0, ptr %tmp22, align 4 647 br label %bb23 648 649bb23: 650 ret void 651} 652 653; In this test there's a single bound, do not generate runtime checks. 654define void @single_membound(ptr %arg, ptr %arg1, double %x) { 655; CHECK-LABEL: @single_membound( 656; CHECK-NEXT: entry: 657; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds double, ptr [[ARG:%.*]], i64 1 658; CHECK-NEXT: [[TMP:%.*]] = fsub double [[X:%.*]], 9.900000e+01 659; CHECK-NEXT: store double [[TMP]], ptr [[TMP9]], align 8 660; CHECK-NEXT: [[TMP12:%.*]] = load double, ptr [[ARG1:%.*]], align 8 661; CHECK-NEXT: [[TMP13:%.*]] = fsub double 1.000000e+00, [[TMP12]] 662; CHECK-NEXT: br label [[BB15:%.*]] 663; CHECK: bb15: 664; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x double> poison, double [[TMP]], i32 0 665; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x double> [[TMP0]], double [[TMP13]], i32 1 666; CHECK-NEXT: [[TMP2:%.*]] = fmul <2 x double> [[TMP1]], <double 2.000000e+01, double 3.000000e+01> 667; CHECK-NEXT: store <2 x double> [[TMP2]], ptr [[TMP9]], align 8 668; CHECK-NEXT: ret void 669; 670entry: 671 %tmp = fsub double %x, 99.0 672 %tmp9 = getelementptr inbounds double, ptr %arg, i64 1 673 store double %tmp, ptr %tmp9, align 8 674 %tmp12 = load double, ptr %arg1, align 8 675 %tmp13 = fsub double 1.0, %tmp12 676 %tmp14 = getelementptr inbounds double, ptr %arg, i64 2 677 br label %bb15 678 679bb15: 680 %tmp16 = fmul double %tmp, 20.0 681 store double %tmp16, ptr %tmp9, align 8 682 %tmp17 = fmul double %tmp13, 30.0 683 store double %tmp17, ptr %tmp14, align 8 684 ret void 685} 686 687%struct.2 = type { [4 x float] } 688 689; Make sure we do not crash when we encounter a SCEVCouldNotCompute. 690define void @no_lcssa_phi(ptr %A, ptr %B, i1 %c) { 691; CHECK-LABEL: @no_lcssa_phi( 692; CHECK-NEXT: bb: 693; CHECK-NEXT: br label [[LOOP:%.*]] 694; CHECK: loop: 695; CHECK-NEXT: [[PTR_PHI:%.*]] = phi ptr [ [[A:%.*]], [[BB:%.*]] ], [ null, [[LOOP]] ] 696; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 697; CHECK: exit: 698; CHECK-NEXT: [[L_0:%.*]] = load float, ptr [[B:%.*]], align 8 699; CHECK-NEXT: [[ADD_0:%.*]] = fadd float [[L_0]], 1.000000e+01 700; CHECK-NEXT: [[MUL_0:%.*]] = fmul float [[ADD_0]], 3.000000e+01 701; CHECK-NEXT: store float [[MUL_0]], ptr [[PTR_PHI]], align 8 702; CHECK-NEXT: [[B_GEP_1:%.*]] = getelementptr inbounds float, ptr [[B]], i64 1 703; CHECK-NEXT: [[L_1:%.*]] = load float, ptr [[B_GEP_1]], align 8 704; CHECK-NEXT: [[ADD_1:%.*]] = fadd float [[L_1]], 1.000000e+01 705; CHECK-NEXT: [[MUL_1:%.*]] = fmul float [[ADD_1]], 3.000000e+01 706; CHECK-NEXT: [[A_GEP_1:%.*]] = getelementptr inbounds [[STRUCT_2:%.*]], ptr [[PTR_PHI]], i64 0, i32 0, i32 1 707; CHECK-NEXT: store float [[MUL_1]], ptr [[A_GEP_1]], align 8 708; CHECK-NEXT: [[B_GEP_2:%.*]] = getelementptr inbounds float, ptr [[B]], i64 2 709; CHECK-NEXT: [[L_2:%.*]] = load float, ptr [[B_GEP_2]], align 8 710; CHECK-NEXT: [[ADD_2:%.*]] = fadd float [[L_2]], 1.000000e+01 711; CHECK-NEXT: [[MUL_2:%.*]] = fmul float [[ADD_2]], 3.000000e+01 712; CHECK-NEXT: [[A_GEP_2:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI]], i64 0, i32 0, i32 2 713; CHECK-NEXT: store float [[MUL_2]], ptr [[A_GEP_2]], align 8 714; CHECK-NEXT: [[B_GEP_3:%.*]] = getelementptr inbounds float, ptr [[B]], i64 3 715; CHECK-NEXT: [[L_3:%.*]] = load float, ptr [[B_GEP_3]], align 8 716; CHECK-NEXT: [[ADD_3:%.*]] = fadd float [[L_3]], 1.000000e+01 717; CHECK-NEXT: [[MUL_3:%.*]] = fmul float [[ADD_3]], 3.000000e+01 718; CHECK-NEXT: [[A_GEP_3:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI]], i64 0, i32 0, i32 3 719; CHECK-NEXT: store float [[MUL_3]], ptr [[A_GEP_3]], align 8 720; CHECK-NEXT: ret void 721; 722bb: 723 br label %loop 724 725loop: 726 %ptr.phi = phi ptr [ %A, %bb ], [ null, %loop ] 727 br i1 %c, label %exit, label %loop 728 729exit: 730 %l.0 = load float, ptr %B, align 8 731 %add.0 = fadd float %l.0, 10.0 732 %mul.0 = fmul float %add.0, 30.0 733 store float %mul.0, ptr %ptr.phi, align 8 734 %B.gep.1 = getelementptr inbounds float, ptr %B, i64 1 735 %l.1 = load float, ptr %B.gep.1, align 8 736 %add.1 = fadd float %l.1, 10.0 737 %mul.1 = fmul float %add.1, 30.0 738 %A.gep.1 = getelementptr inbounds %struct.2, ptr %ptr.phi, i64 0, i32 0, i32 1 739 store float %mul.1, ptr %A.gep.1, align 8 740 %B.gep.2 = getelementptr inbounds float, ptr %B, i64 2 741 %l.2 = load float, ptr %B.gep.2, align 8 742 %add.2 = fadd float %l.2, 10.0 743 %mul.2 = fmul float %add.2, 30.0 744 %A.gep.2 = getelementptr inbounds %struct.2, ptr %ptr.phi, i64 0, i32 0, i32 2 745 store float %mul.2, ptr %A.gep.2, align 8 746 %B.gep.3 = getelementptr inbounds float, ptr %B, i64 3 747 %l.3 = load float, ptr %B.gep.3, align 8 748 %add.3 = fadd float %l.3, 10.0 749 %mul.3 = fmul float %add.3, 30.0 750 %A.gep.3 = getelementptr inbounds %struct.2, ptr %ptr.phi, i64 0, i32 0, i32 3 751 store float %mul.3, ptr %A.gep.3, align 8 752 ret void 753} 754 755; Make sure lcssa phis as pointer bases are handled properly. 756define void @lcssa_phi(ptr %A, ptr %B, i1 %c) { 757; CHECK-LABEL: @lcssa_phi( 758; CHECK-NEXT: bb: 759; CHECK-NEXT: br label [[LOOP:%.*]] 760; CHECK: loop: 761; CHECK-NEXT: [[PTR_PHI:%.*]] = phi ptr [ [[A:%.*]], [[BB:%.*]] ], [ null, [[LOOP]] ] 762; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 763; CHECK: exit: 764; CHECK-NEXT: [[PTR_PHI_LCSSA:%.*]] = phi ptr [ [[PTR_PHI]], [[LOOP]] ] 765; CHECK-NEXT: [[L_0:%.*]] = load float, ptr [[B:%.*]], align 8 766; CHECK-NEXT: [[ADD_0:%.*]] = fadd float [[L_0]], 1.000000e+01 767; CHECK-NEXT: [[MUL_0:%.*]] = fmul float [[ADD_0]], 3.000000e+01 768; CHECK-NEXT: store float [[MUL_0]], ptr [[PTR_PHI_LCSSA]], align 8 769; CHECK-NEXT: [[B_GEP_1:%.*]] = getelementptr inbounds float, ptr [[B]], i64 1 770; CHECK-NEXT: [[L_1:%.*]] = load float, ptr [[B_GEP_1]], align 8 771; CHECK-NEXT: [[ADD_1:%.*]] = fadd float [[L_1]], 1.000000e+01 772; CHECK-NEXT: [[MUL_1:%.*]] = fmul float [[ADD_1]], 3.000000e+01 773; CHECK-NEXT: [[A_GEP_1:%.*]] = getelementptr inbounds [[STRUCT_2:%.*]], ptr [[PTR_PHI_LCSSA]], i64 0, i32 0, i32 1 774; CHECK-NEXT: store float [[MUL_1]], ptr [[A_GEP_1]], align 8 775; CHECK-NEXT: [[B_GEP_2:%.*]] = getelementptr inbounds float, ptr [[B]], i64 2 776; CHECK-NEXT: [[L_2:%.*]] = load float, ptr [[B_GEP_2]], align 8 777; CHECK-NEXT: [[ADD_2:%.*]] = fadd float [[L_2]], 1.000000e+01 778; CHECK-NEXT: [[MUL_2:%.*]] = fmul float [[ADD_2]], 3.000000e+01 779; CHECK-NEXT: [[A_GEP_2:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI_LCSSA]], i64 0, i32 0, i32 2 780; CHECK-NEXT: store float [[MUL_2]], ptr [[A_GEP_2]], align 8 781; CHECK-NEXT: [[B_GEP_3:%.*]] = getelementptr inbounds float, ptr [[B]], i64 3 782; CHECK-NEXT: [[L_3:%.*]] = load float, ptr [[B_GEP_3]], align 8 783; CHECK-NEXT: [[ADD_3:%.*]] = fadd float [[L_3]], 1.000000e+01 784; CHECK-NEXT: [[MUL_3:%.*]] = fmul float [[ADD_3]], 3.000000e+01 785; CHECK-NEXT: [[A_GEP_3:%.*]] = getelementptr inbounds [[STRUCT_2]], ptr [[PTR_PHI_LCSSA]], i64 0, i32 0, i32 3 786; CHECK-NEXT: store float [[MUL_3]], ptr [[A_GEP_3]], align 8 787; CHECK-NEXT: ret void 788; 789bb: 790 br label %loop 791 792loop: 793 %ptr.phi = phi ptr [ %A, %bb ], [ null, %loop ] 794 br i1 %c, label %exit, label %loop 795 796exit: 797 %ptr.phi.lcssa = phi ptr [ %ptr.phi, %loop ] 798 %l.0 = load float, ptr %B, align 8 799 %add.0 = fadd float %l.0, 10.0 800 %mul.0 = fmul float %add.0, 30.0 801 store float %mul.0, ptr %ptr.phi.lcssa, align 8 802 %B.gep.1 = getelementptr inbounds float, ptr %B, i64 1 803 %l.1 = load float, ptr %B.gep.1, align 8 804 %add.1 = fadd float %l.1, 10.0 805 %mul.1 = fmul float %add.1, 30.0 806 %A.gep.1 = getelementptr inbounds %struct.2, ptr %ptr.phi.lcssa, i64 0, i32 0, i32 1 807 store float %mul.1, ptr %A.gep.1, align 8 808 %B.gep.2 = getelementptr inbounds float, ptr %B, i64 2 809 %l.2 = load float, ptr %B.gep.2, align 8 810 %add.2 = fadd float %l.2, 10.0 811 %mul.2 = fmul float %add.2, 30.0 812 %A.gep.2 = getelementptr inbounds %struct.2, ptr %ptr.phi.lcssa, i64 0, i32 0, i32 2 813 store float %mul.2, ptr %A.gep.2, align 8 814 %B.gep.3 = getelementptr inbounds float, ptr %B, i64 3 815 %l.3 = load float, ptr %B.gep.3, align 8 816 %add.3 = fadd float %l.3, 10.0 817 %mul.3 = fmul float %add.3, 30.0 818 %A.gep.3 = getelementptr inbounds %struct.2, ptr %ptr.phi.lcssa, i64 0, i32 0, i32 3 819 store float %mul.3, ptr %A.gep.3, align 8 820 ret void 821} 822 823%struct.spam = type { [60 x i32], i32, [12 x i8] } 824 825declare void @foo(ptr) 826 827; Test case with a basic block where parts can be vectorized without versioning. 828define i32 @block_partly_vectorized_without_versioning(ptr readonly %arg, ptr nocapture readonly %arg1, ptr nocapture %arg2, ptr nocapture readonly %arg3, ptr %A, ptr %B) { 829; CHECK-LABEL: @block_partly_vectorized_without_versioning( 830; CHECK-NEXT: bb: 831; CHECK-NEXT: [[T:%.*]] = alloca <16 x i8>, align 16 832; CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[ARG3:%.*]], i64 1 833; CHECK-NEXT: [[T6:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 2 834; CHECK-NEXT: [[T7:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 3 835; CHECK-NEXT: [[T8:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 4 836; CHECK-NEXT: [[T9:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 5 837; CHECK-NEXT: [[T10:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 6 838; CHECK-NEXT: [[T11:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 7 839; CHECK-NEXT: [[T12:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 8 840; CHECK-NEXT: [[T13:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 9 841; CHECK-NEXT: [[T14:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 10 842; CHECK-NEXT: [[T15:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 11 843; CHECK-NEXT: [[T16:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 12 844; CHECK-NEXT: [[T17:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 13 845; CHECK-NEXT: [[T18:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 14 846; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[A:%.*]], align 1 847; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i8>, ptr [[B:%.*]], align 1 848; CHECK-NEXT: [[TMP2:%.*]] = xor <16 x i8> [[TMP0]], [[TMP1]] 849; CHECK-NEXT: store <16 x i8> [[TMP2]], ptr [[ARG1:%.*]], align 1 850; CHECK-NEXT: [[T21:%.*]] = getelementptr inbounds i8, ptr [[ARG3]], i64 15 851; CHECK-NEXT: call void @foo(ptr nonnull [[T]]) 852; CHECK-NEXT: [[T26:%.*]] = load i8, ptr [[ARG3]], align 1 853; CHECK-NEXT: [[T27:%.*]] = load i8, ptr [[ARG2:%.*]], align 1 854; CHECK-NEXT: [[T28:%.*]] = xor i8 [[T27]], [[T26]] 855; CHECK-NEXT: store i8 [[T28]], ptr [[ARG2]], align 1 856; CHECK-NEXT: [[T29:%.*]] = load i8, ptr [[T5]], align 1 857; CHECK-NEXT: [[T30:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 1 858; CHECK-NEXT: [[T31:%.*]] = load i8, ptr [[T30]], align 1 859; CHECK-NEXT: [[T32:%.*]] = xor i8 [[T31]], [[T29]] 860; CHECK-NEXT: store i8 [[T32]], ptr [[T30]], align 1 861; CHECK-NEXT: [[T33:%.*]] = load i8, ptr [[T6]], align 1 862; CHECK-NEXT: [[T34:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 2 863; CHECK-NEXT: [[T35:%.*]] = load i8, ptr [[T34]], align 1 864; CHECK-NEXT: [[T36:%.*]] = xor i8 [[T35]], [[T33]] 865; CHECK-NEXT: store i8 [[T36]], ptr [[T34]], align 1 866; CHECK-NEXT: [[T37:%.*]] = load i8, ptr [[T7]], align 1 867; CHECK-NEXT: [[T38:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 3 868; CHECK-NEXT: [[T39:%.*]] = load i8, ptr [[T38]], align 1 869; CHECK-NEXT: [[T40:%.*]] = xor i8 [[T39]], [[T37]] 870; CHECK-NEXT: store i8 [[T40]], ptr [[T38]], align 1 871; CHECK-NEXT: [[T41:%.*]] = load i8, ptr [[T8]], align 1 872; CHECK-NEXT: [[T42:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 4 873; CHECK-NEXT: [[T43:%.*]] = load i8, ptr [[T42]], align 1 874; CHECK-NEXT: [[T44:%.*]] = xor i8 [[T43]], [[T41]] 875; CHECK-NEXT: store i8 [[T44]], ptr [[T42]], align 1 876; CHECK-NEXT: [[T45:%.*]] = load i8, ptr [[T9]], align 1 877; CHECK-NEXT: [[T46:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 5 878; CHECK-NEXT: [[T47:%.*]] = load i8, ptr [[T46]], align 1 879; CHECK-NEXT: [[T48:%.*]] = xor i8 [[T47]], [[T45]] 880; CHECK-NEXT: store i8 [[T48]], ptr [[T46]], align 1 881; CHECK-NEXT: [[T49:%.*]] = load i8, ptr [[T10]], align 1 882; CHECK-NEXT: [[T50:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 6 883; CHECK-NEXT: [[T51:%.*]] = load i8, ptr [[T50]], align 1 884; CHECK-NEXT: [[T52:%.*]] = xor i8 [[T51]], [[T49]] 885; CHECK-NEXT: store i8 [[T52]], ptr [[T50]], align 1 886; CHECK-NEXT: [[T53:%.*]] = load i8, ptr [[T11]], align 1 887; CHECK-NEXT: [[T54:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 7 888; CHECK-NEXT: [[T55:%.*]] = load i8, ptr [[T54]], align 1 889; CHECK-NEXT: [[T56:%.*]] = xor i8 [[T55]], [[T53]] 890; CHECK-NEXT: store i8 [[T56]], ptr [[T54]], align 1 891; CHECK-NEXT: [[T57:%.*]] = load i8, ptr [[T12]], align 1 892; CHECK-NEXT: [[T58:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 8 893; CHECK-NEXT: [[T59:%.*]] = load i8, ptr [[T58]], align 1 894; CHECK-NEXT: [[T60:%.*]] = xor i8 [[T59]], [[T57]] 895; CHECK-NEXT: store i8 [[T60]], ptr [[T58]], align 1 896; CHECK-NEXT: [[T61:%.*]] = load i8, ptr [[T13]], align 1 897; CHECK-NEXT: [[T62:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 9 898; CHECK-NEXT: [[T63:%.*]] = load i8, ptr [[T62]], align 1 899; CHECK-NEXT: [[T64:%.*]] = xor i8 [[T63]], [[T61]] 900; CHECK-NEXT: store i8 [[T64]], ptr [[T62]], align 1 901; CHECK-NEXT: [[T65:%.*]] = load i8, ptr [[T14]], align 1 902; CHECK-NEXT: [[T66:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 10 903; CHECK-NEXT: [[T67:%.*]] = load i8, ptr [[T66]], align 1 904; CHECK-NEXT: [[T68:%.*]] = xor i8 [[T67]], [[T65]] 905; CHECK-NEXT: store i8 [[T68]], ptr [[T66]], align 1 906; CHECK-NEXT: [[T69:%.*]] = load i8, ptr [[T15]], align 1 907; CHECK-NEXT: [[T70:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 11 908; CHECK-NEXT: [[T71:%.*]] = load i8, ptr [[T70]], align 1 909; CHECK-NEXT: [[T72:%.*]] = xor i8 [[T71]], [[T69]] 910; CHECK-NEXT: store i8 [[T72]], ptr [[T70]], align 1 911; CHECK-NEXT: [[T73:%.*]] = load i8, ptr [[T16]], align 1 912; CHECK-NEXT: [[T74:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 12 913; CHECK-NEXT: [[T75:%.*]] = load i8, ptr [[T74]], align 1 914; CHECK-NEXT: [[T76:%.*]] = xor i8 [[T75]], [[T73]] 915; CHECK-NEXT: store i8 [[T76]], ptr [[T74]], align 1 916; CHECK-NEXT: [[T77:%.*]] = load i8, ptr [[T17]], align 1 917; CHECK-NEXT: [[T78:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 13 918; CHECK-NEXT: [[T79:%.*]] = load i8, ptr [[T78]], align 1 919; CHECK-NEXT: [[T80:%.*]] = xor i8 [[T79]], [[T77]] 920; CHECK-NEXT: store i8 [[T80]], ptr [[T78]], align 1 921; CHECK-NEXT: [[T81:%.*]] = load i8, ptr [[T18]], align 1 922; CHECK-NEXT: [[T82:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 14 923; CHECK-NEXT: [[T83:%.*]] = load i8, ptr [[T82]], align 1 924; CHECK-NEXT: [[T84:%.*]] = xor i8 [[T83]], [[T81]] 925; CHECK-NEXT: store i8 [[T84]], ptr [[T82]], align 1 926; CHECK-NEXT: [[T85:%.*]] = load i8, ptr [[T21]], align 1 927; CHECK-NEXT: [[T86:%.*]] = getelementptr inbounds i8, ptr [[ARG2]], i64 15 928; CHECK-NEXT: [[T87:%.*]] = load i8, ptr [[T86]], align 1 929; CHECK-NEXT: [[T88:%.*]] = xor i8 [[T87]], [[T85]] 930; CHECK-NEXT: store i8 [[T88]], ptr [[T86]], align 1 931; CHECK-NEXT: ret i32 1 932; 933bb: 934 %t = alloca <16 x i8>, align 16 935 %t5 = getelementptr inbounds i8, ptr %arg3, i64 1 936 %t6 = getelementptr inbounds i8, ptr %arg3, i64 2 937 %t7 = getelementptr inbounds i8, ptr %arg3, i64 3 938 %t8 = getelementptr inbounds i8, ptr %arg3, i64 4 939 %t9 = getelementptr inbounds i8, ptr %arg3, i64 5 940 %t10 = getelementptr inbounds i8, ptr %arg3, i64 6 941 %t11 = getelementptr inbounds i8, ptr %arg3, i64 7 942 %t12 = getelementptr inbounds i8, ptr %arg3, i64 8 943 %t13 = getelementptr inbounds i8, ptr %arg3, i64 9 944 %t14 = getelementptr inbounds i8, ptr %arg3, i64 10 945 %t15 = getelementptr inbounds i8, ptr %arg3, i64 11 946 %t16 = getelementptr inbounds i8, ptr %arg3, i64 12 947 %t17 = getelementptr inbounds i8, ptr %arg3, i64 13 948 %t18 = getelementptr inbounds i8, ptr %arg3, i64 14 949 %A.0 = load i8, ptr %A 950 %B.0 = load i8, ptr %B 951 %xor.0 = xor i8 %A.0, %B.0 952 %A.gep.1 = getelementptr i8, ptr %A, i64 1 953 %A.1 = load i8, ptr %A.gep.1 954 %B.gep.1 = getelementptr i8, ptr %B, i64 1 955 %B.1 = load i8, ptr %B.gep.1 956 %xor.1 = xor i8 %A.1, %B.1 957 %A.gep.2 = getelementptr i8, ptr %A, i64 2 958 %A.2 = load i8, ptr %A.gep.2 959 %B.gep.2 = getelementptr i8, ptr %B, i64 2 960 %B.2 = load i8, ptr %B.gep.2 961 %xor.2 = xor i8 %A.2, %B.2 962 %A.gep.3 = getelementptr i8, ptr %A, i64 3 963 %A.3 = load i8, ptr %A.gep.3 964 %B.gep.3 = getelementptr i8, ptr %B, i64 3 965 %B.3 = load i8, ptr %B.gep.3 966 %xor.3 = xor i8 %A.3, %B.3 967 %A.gep.4 = getelementptr i8, ptr %A, i64 4 968 %A.4 = load i8, ptr %A.gep.4 969 %B.gep.4 = getelementptr i8, ptr %B, i64 4 970 %B.4 = load i8, ptr %B.gep.4 971 %xor.4 = xor i8 %A.4, %B.4 972 %A.gep.5 = getelementptr i8, ptr %A, i64 5 973 %A.5 = load i8, ptr %A.gep.5 974 %B.gep.5 = getelementptr i8, ptr %B, i64 5 975 %B.5 = load i8, ptr %B.gep.5 976 %xor.5 = xor i8 %A.5, %B.5 977 %A.gep.6 = getelementptr i8, ptr %A, i64 6 978 %A.6 = load i8, ptr %A.gep.6 979 %B.gep.6 = getelementptr i8, ptr %B, i64 6 980 %B.6 = load i8, ptr %B.gep.6 981 %xor.6 = xor i8 %A.6, %B.6 982 %A.gep.7 = getelementptr i8, ptr %A, i64 7 983 %A.7 = load i8, ptr %A.gep.7 984 %B.gep.7 = getelementptr i8, ptr %B, i64 7 985 %B.7 = load i8, ptr %B.gep.7 986 %xor.7 = xor i8 %A.7, %B.7 987 %A.gep.8 = getelementptr i8, ptr %A, i64 8 988 %A.8 = load i8, ptr %A.gep.8 989 %B.gep.8 = getelementptr i8, ptr %B, i64 8 990 %B.8 = load i8, ptr %B.gep.8 991 %xor.8 = xor i8 %A.8, %B.8 992 %A.gep.9 = getelementptr i8, ptr %A, i64 9 993 %A.9 = load i8, ptr %A.gep.9 994 %B.gep.9 = getelementptr i8, ptr %B, i64 9 995 %B.9 = load i8, ptr %B.gep.9 996 %xor.9 = xor i8 %A.9, %B.9 997 %A.gep.10 = getelementptr i8, ptr %A, i64 10 998 %A.10 = load i8, ptr %A.gep.10 999 %B.gep.10 = getelementptr i8, ptr %B, i64 10 1000 %B.10 = load i8, ptr %B.gep.10 1001 %xor.10 = xor i8 %A.10, %B.10 1002 %A.gep.11 = getelementptr i8, ptr %A, i64 11 1003 %A.11 = load i8, ptr %A.gep.11 1004 %B.gep.11 = getelementptr i8, ptr %B, i64 11 1005 %B.11 = load i8, ptr %B.gep.11 1006 %xor.11 = xor i8 %A.11, %B.11 1007 %A.gep.12 = getelementptr i8, ptr %A, i64 12 1008 %A.12 = load i8, ptr %A.gep.12 1009 %B.gep.12 = getelementptr i8, ptr %B, i64 12 1010 %B.12 = load i8, ptr %B.gep.12 1011 %xor.12 = xor i8 %A.12, %B.12 1012 %A.gep.13 = getelementptr i8, ptr %A, i64 13 1013 %A.13 = load i8, ptr %A.gep.13 1014 %B.gep.13 = getelementptr i8, ptr %B, i64 13 1015 %B.13 = load i8, ptr %B.gep.13 1016 %xor.13 = xor i8 %A.13, %B.13 1017 %A.gep.14 = getelementptr i8, ptr %A, i64 14 1018 %A.14 = load i8, ptr %A.gep.14 1019 %B.gep.14 = getelementptr i8, ptr %B, i64 14 1020 %B.14 = load i8, ptr %B.gep.14 1021 %xor.14 = xor i8 %A.14, %B.14 1022 %A.gep.15 = getelementptr i8, ptr %A, i64 15 1023 %A.15 = load i8, ptr %A.gep.15 1024 %B.gep.15 = getelementptr i8, ptr %B, i64 15 1025 %B.15 = load i8, ptr %B.gep.15 1026 %xor.15 = xor i8 %A.15, %B.15 1027 store i8 %xor.0, ptr %arg1 1028 %R.gep.1 = getelementptr i8, ptr %arg1, i64 1 1029 store i8 %xor.1, ptr %R.gep.1 1030 %R.gep.2 = getelementptr i8, ptr %arg1, i64 2 1031 store i8 %xor.2, ptr %R.gep.2 1032 %R.gep.3 = getelementptr i8, ptr %arg1, i64 3 1033 store i8 %xor.3, ptr %R.gep.3 1034 %R.gep.4 = getelementptr i8, ptr %arg1, i64 4 1035 store i8 %xor.4, ptr %R.gep.4 1036 %R.gep.5 = getelementptr i8, ptr %arg1, i64 5 1037 store i8 %xor.5, ptr %R.gep.5 1038 %R.gep.6 = getelementptr i8, ptr %arg1, i64 6 1039 store i8 %xor.6, ptr %R.gep.6 1040 %R.gep.7 = getelementptr i8, ptr %arg1, i64 7 1041 store i8 %xor.7, ptr %R.gep.7 1042 %R.gep.8 = getelementptr i8, ptr %arg1, i64 8 1043 store i8 %xor.8, ptr %R.gep.8 1044 %R.gep.9 = getelementptr i8, ptr %arg1, i64 9 1045 store i8 %xor.9, ptr %R.gep.9 1046 %R.gep.10 = getelementptr i8, ptr %arg1, i64 10 1047 store i8 %xor.10, ptr %R.gep.10 1048 %R.gep.11 = getelementptr i8, ptr %arg1, i64 11 1049 store i8 %xor.11, ptr %R.gep.11 1050 %R.gep.12 = getelementptr i8, ptr %arg1, i64 12 1051 store i8 %xor.12, ptr %R.gep.12 1052 %R.gep.13 = getelementptr i8, ptr %arg1, i64 13 1053 store i8 %xor.13, ptr %R.gep.13 1054 %R.gep.14 = getelementptr i8, ptr %arg1, i64 14 1055 store i8 %xor.14, ptr %R.gep.14 1056 %R.gep.15 = getelementptr i8, ptr %arg1, i64 15 1057 store i8 %xor.15, ptr %R.gep.15 1058 1059 1060 %t21 = getelementptr inbounds i8, ptr %arg3, i64 15 1061 1062 call void @foo(ptr nonnull %t) 1063 %t26 = load i8, ptr %arg3, align 1 1064 %t27 = load i8, ptr %arg2, align 1 1065 %t28 = xor i8 %t27, %t26 1066 store i8 %t28, ptr %arg2, align 1 1067 %t29 = load i8, ptr %t5, align 1 1068 %t30 = getelementptr inbounds i8, ptr %arg2, i64 1 1069 %t31 = load i8, ptr %t30, align 1 1070 %t32 = xor i8 %t31, %t29 1071 store i8 %t32, ptr %t30, align 1 1072 %t33 = load i8, ptr %t6, align 1 1073 %t34 = getelementptr inbounds i8, ptr %arg2, i64 2 1074 %t35 = load i8, ptr %t34, align 1 1075 %t36 = xor i8 %t35, %t33 1076 store i8 %t36, ptr %t34, align 1 1077 %t37 = load i8, ptr %t7, align 1 1078 %t38 = getelementptr inbounds i8, ptr %arg2, i64 3 1079 %t39 = load i8, ptr %t38, align 1 1080 %t40 = xor i8 %t39, %t37 1081 store i8 %t40, ptr %t38, align 1 1082 %t41 = load i8, ptr %t8, align 1 1083 %t42 = getelementptr inbounds i8, ptr %arg2, i64 4 1084 %t43 = load i8, ptr %t42, align 1 1085 %t44 = xor i8 %t43, %t41 1086 store i8 %t44, ptr %t42, align 1 1087 %t45 = load i8, ptr %t9, align 1 1088 %t46 = getelementptr inbounds i8, ptr %arg2, i64 5 1089 %t47 = load i8, ptr %t46, align 1 1090 %t48 = xor i8 %t47, %t45 1091 store i8 %t48, ptr %t46, align 1 1092 %t49 = load i8, ptr %t10, align 1 1093 %t50 = getelementptr inbounds i8, ptr %arg2, i64 6 1094 %t51 = load i8, ptr %t50, align 1 1095 %t52 = xor i8 %t51, %t49 1096 store i8 %t52, ptr %t50, align 1 1097 %t53 = load i8, ptr %t11, align 1 1098 %t54 = getelementptr inbounds i8, ptr %arg2, i64 7 1099 %t55 = load i8, ptr %t54, align 1 1100 %t56 = xor i8 %t55, %t53 1101 store i8 %t56, ptr %t54, align 1 1102 %t57 = load i8, ptr %t12, align 1 1103 %t58 = getelementptr inbounds i8, ptr %arg2, i64 8 1104 %t59 = load i8, ptr %t58, align 1 1105 %t60 = xor i8 %t59, %t57 1106 store i8 %t60, ptr %t58, align 1 1107 %t61 = load i8, ptr %t13, align 1 1108 %t62 = getelementptr inbounds i8, ptr %arg2, i64 9 1109 %t63 = load i8, ptr %t62, align 1 1110 %t64 = xor i8 %t63, %t61 1111 store i8 %t64, ptr %t62, align 1 1112 %t65 = load i8, ptr %t14, align 1 1113 %t66 = getelementptr inbounds i8, ptr %arg2, i64 10 1114 %t67 = load i8, ptr %t66, align 1 1115 %t68 = xor i8 %t67, %t65 1116 store i8 %t68, ptr %t66, align 1 1117 %t69 = load i8, ptr %t15, align 1 1118 %t70 = getelementptr inbounds i8, ptr %arg2, i64 11 1119 %t71 = load i8, ptr %t70, align 1 1120 %t72 = xor i8 %t71, %t69 1121 store i8 %t72, ptr %t70, align 1 1122 %t73 = load i8, ptr %t16, align 1 1123 %t74 = getelementptr inbounds i8, ptr %arg2, i64 12 1124 %t75 = load i8, ptr %t74, align 1 1125 %t76 = xor i8 %t75, %t73 1126 store i8 %t76, ptr %t74, align 1 1127 %t77 = load i8, ptr %t17, align 1 1128 %t78 = getelementptr inbounds i8, ptr %arg2, i64 13 1129 %t79 = load i8, ptr %t78, align 1 1130 %t80 = xor i8 %t79, %t77 1131 store i8 %t80, ptr %t78, align 1 1132 %t81 = load i8, ptr %t18, align 1 1133 %t82 = getelementptr inbounds i8, ptr %arg2, i64 14 1134 %t83 = load i8, ptr %t82, align 1 1135 %t84 = xor i8 %t83, %t81 1136 store i8 %t84, ptr %t82, align 1 1137 %t85 = load i8, ptr %t21, align 1 1138 %t86 = getelementptr inbounds i8, ptr %arg2, i64 15 1139 %t87 = load i8, ptr %t86, align 1 1140 %t88 = xor i8 %t87, %t85 1141 store i8 %t88, ptr %t86, align 1 1142 ret i32 1 1143} 1144 1145; A test case where instructions required to compute the pointer bounds get 1146; vectorized before versioning. Make sure there is no crash. 1147define void @crash_instructions_deleted(ptr %t, ptr %a, ptr noalias %ptr) { 1148; CHECK-LABEL: @crash_instructions_deleted( 1149; CHECK-NEXT: bb: 1150; CHECK-NEXT: [[T15:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 2 1151; CHECK-NEXT: store <2 x i32> <i32 0, i32 10>, ptr [[T15]], align 8 1152; CHECK-NEXT: [[T17:%.*]] = load ptr, ptr [[PTR:%.*]], align 8 1153; CHECK-NEXT: br label [[BB18:%.*]] 1154; CHECK: bb18: 1155; CHECK-NEXT: [[T19:%.*]] = sext i32 0 to i64 1156; CHECK-NEXT: [[T20:%.*]] = add nsw i64 1, [[T19]] 1157; CHECK-NEXT: [[T21:%.*]] = getelementptr inbounds i32, ptr [[T17]], i64 [[T20]] 1158; CHECK-NEXT: [[T23:%.*]] = getelementptr inbounds i8, ptr [[T21]], i64 1 1159; CHECK-NEXT: [[T24:%.*]] = getelementptr inbounds i8, ptr [[T21]], i64 2 1160; CHECK-NEXT: [[T25:%.*]] = getelementptr inbounds i8, ptr [[T21]], i64 3 1161; CHECK-NEXT: [[T26:%.*]] = load i8, ptr [[T21]], align 1 1162; CHECK-NEXT: [[T27:%.*]] = uitofp i8 [[T26]] to float 1163; CHECK-NEXT: [[T28:%.*]] = fdiv float [[T27]], 2.550000e+02 1164; CHECK-NEXT: store float [[T28]], ptr [[T:%.*]], align 8 1165; CHECK-NEXT: [[T30:%.*]] = load i8, ptr [[T23]], align 1 1166; CHECK-NEXT: [[T31:%.*]] = uitofp i8 [[T30]] to float 1167; CHECK-NEXT: [[T32:%.*]] = fdiv float [[T31]], 2.550000e+02 1168; CHECK-NEXT: [[T33:%.*]] = getelementptr inbounds float, ptr [[T]], i64 1 1169; CHECK-NEXT: store float [[T32]], ptr [[T33]], align 4 1170; CHECK-NEXT: [[T34:%.*]] = load i8, ptr [[T24]], align 1 1171; CHECK-NEXT: [[T35:%.*]] = uitofp i8 [[T34]] to float 1172; CHECK-NEXT: [[T36:%.*]] = fdiv float [[T35]], 2.550000e+02 1173; CHECK-NEXT: [[T37:%.*]] = getelementptr inbounds float, ptr [[T]], i64 2 1174; CHECK-NEXT: store float [[T36]], ptr [[T37]], align 8 1175; CHECK-NEXT: [[T38:%.*]] = load i8, ptr [[T25]], align 1 1176; CHECK-NEXT: [[T39:%.*]] = uitofp i8 [[T38]] to float 1177; CHECK-NEXT: [[T40:%.*]] = fdiv float [[T39]], 2.550000e+02 1178; CHECK-NEXT: [[T41:%.*]] = getelementptr inbounds float, ptr [[T]], i64 3 1179; CHECK-NEXT: store float [[T40]], ptr [[T41]], align 4 1180; CHECK-NEXT: ret void 1181; 1182bb: 1183 %t6 = icmp slt i32 10, 0 1184 %t7 = icmp sgt i32 20, 20 1185 %t9 = select i1 %t7, i32 5, i32 0 1186 %t10 = select i1 %t6, i32 0, i32 %t9 1187 %t11 = icmp slt i32 10, 0 1188 %t12 = icmp sgt i32 20, 20 1189 %t13 = select i1 %t12, i32 5, i32 10 1190 %t14 = select i1 %t11, i32 0, i32 %t13 1191 %t15 = getelementptr inbounds i32, ptr %a, i32 2 1192 store i32 %t10, ptr %t15, align 8 1193 %t16 = getelementptr inbounds i32, ptr %a, i32 3 1194 store i32 %t14, ptr %t16, align 4 1195 %t17 = load ptr, ptr %ptr, align 8 1196 br label %bb18 1197 1198bb18: ; preds = %bb5 1199 %t19 = sext i32 %t10 to i64 1200 %t20 = add nsw i64 1, %t19 1201 %t21 = getelementptr inbounds i32, ptr %t17, i64 %t20 1202 %t23 = getelementptr inbounds i8, ptr %t21, i64 1 1203 %t24 = getelementptr inbounds i8, ptr %t21, i64 2 1204 %t25 = getelementptr inbounds i8, ptr %t21, i64 3 1205 %t26 = load i8, ptr %t21, align 1 1206 %t27 = uitofp i8 %t26 to float 1207 %t28 = fdiv float %t27, 2.550000e+02 1208 store float %t28, ptr %t, align 8 1209 %t30 = load i8, ptr %t23, align 1 1210 %t31 = uitofp i8 %t30 to float 1211 %t32 = fdiv float %t31, 2.550000e+02 1212 %t33 = getelementptr inbounds float, ptr %t, i64 1 1213 store float %t32, ptr %t33, align 4 1214 %t34 = load i8, ptr %t24, align 1 1215 %t35 = uitofp i8 %t34 to float 1216 %t36 = fdiv float %t35, 2.550000e+02 1217 %t37 = getelementptr inbounds float, ptr %t, i64 2 1218 store float %t36, ptr %t37, align 8 1219 %t38 = load i8, ptr %t25, align 1 1220 %t39 = uitofp i8 %t38 to float 1221 %t40 = fdiv float %t39, 2.550000e+02 1222 %t41 = getelementptr inbounds float, ptr %t, i64 3 1223 store float %t40, ptr %t41, align 4 1224 ret void 1225} 1226 1227; A test case where there are no instructions accessing a tracked object in a 1228; block for which versioning was requested. 1229define void @crash_no_tracked_instructions(ptr %arg, ptr %arg.2, ptr %arg.3, i1 %c) { 1230; CHECK-LABEL: @crash_no_tracked_instructions( 1231; CHECK-NEXT: entry: 1232; CHECK-NEXT: [[T19:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 1233; CHECK-NEXT: [[T20:%.*]] = load float, ptr [[ARG_3:%.*]], align 4 1234; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x float> <float 0.000000e+00, float poison>, float [[T20]], i32 1 1235; CHECK-NEXT: br i1 [[C:%.*]], label [[BB22:%.*]], label [[BB30:%.*]] 1236; CHECK: bb22: 1237; CHECK-NEXT: [[T23:%.*]] = fmul float [[T20]], 9.900000e+01 1238; CHECK-NEXT: [[T25:%.*]] = getelementptr inbounds float, ptr [[T19]], i64 2 1239; CHECK-NEXT: [[T26:%.*]] = fmul float [[T23]], 1.000000e+01 1240; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x float> poison, float [[T23]], i32 0 1241; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1242; CHECK-NEXT: [[TMP3:%.*]] = fmul <2 x float> [[TMP2]], <float 9.900000e+01, float 1.000000e+01> 1243; CHECK-NEXT: store float [[T26]], ptr [[T25]], align 4 1244; CHECK-NEXT: [[T27:%.*]] = load float, ptr [[ARG_2:%.*]], align 8 1245; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x float> [[TMP3]], splat (float 2.000000e+01) 1246; CHECK-NEXT: br label [[BB30]] 1247; CHECK: bb30: 1248; CHECK-NEXT: [[TMP5:%.*]] = phi <2 x float> [ [[TMP4]], [[BB22]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 1249; CHECK-NEXT: br label [[BB36:%.*]] 1250; CHECK: bb36: 1251; CHECK-NEXT: [[TMP6:%.*]] = fmul <2 x float> [[TMP5]], splat (float 3.000000e+00) 1252; CHECK-NEXT: store <2 x float> [[TMP6]], ptr [[ARG_3]], align 4 1253; CHECK-NEXT: br label [[BB41:%.*]] 1254; CHECK: bb41: 1255; CHECK-NEXT: ret void 1256; 1257entry: 1258 %t19 = load ptr, ptr %arg 1259 %t20 = load float, ptr %arg.3, align 4 1260 br i1 %c, label %bb22, label %bb30 1261 1262bb22: 1263 %t23 = fmul float %t20, 99.0 1264 %t24 = fmul float %t23, 99.0 1265 %t25 = getelementptr inbounds float, ptr %t19, i64 2 1266 %t26 = fmul float %t23, 10.0 1267 store float %t26, ptr %t25, align 4 1268 %t27 = load float, ptr %arg.2, align 8 1269 %t28 = fadd float %t24, 20.0 1270 %t29 = fadd float %t26, 20.0 1271 br label %bb30 1272 1273bb30: 1274 %t31 = phi float [ %t28, %bb22 ], [ 0.0, %entry ] 1275 %t32 = phi float [ %t29, %bb22 ], [ %t20, %entry ] 1276 br label %bb36 1277 1278bb36: 1279 %t37 = fmul float %t31, 3.0 1280 store float %t37, ptr %arg.3, align 4 1281 %t39 = fmul float %t32, 3.0 1282 %t40 = getelementptr inbounds float, ptr %arg.3, i64 1 1283 store float %t39, ptr %t40, align 4 1284 br label %bb41 1285 1286bb41: 1287 ret void 1288} 1289