554 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: %if x86-registered-target %{ opt < %s -passes=slp-vectorizer -S -mtriple=x86_64-apple-macosx10.9.0 | FileCheck %s --check-prefixes=CHECK-X86 %}3; RUN: %if aarch64-registered-target %{ opt < %s -passes=slp-vectorizer -S -mtriple=aarch64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK-AARCH64 %}4 5@A = common global [2000 x double] zeroinitializer, align 166@B = common global [2000 x double] zeroinitializer, align 167@C = common global [2000 x float] zeroinitializer, align 168@D = common global [2000 x float] zeroinitializer, align 169 10; Function Attrs: nounwind ssp uwtable11define void @foo_3double(i32 %u) {12; CHECK-LABEL: @foo_3double(13; CHECK-NEXT: entry:14; CHECK-NEXT: [[U_ADDR:%.*]] = alloca i32, align 415; CHECK-NEXT: store i32 [[U:%.*]], ptr [[U_ADDR]], align 416; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[U]], 317; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[MUL]] to i6418; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 [[IDXPROM]]19; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 [[IDXPROM]]20; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 821; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAYIDX4]], align 822; CHECK-NEXT: [[TMP2:%.*]] = fadd <2 x double> [[TMP0]], [[TMP1]]23; CHECK-NEXT: store <2 x double> [[TMP2]], ptr [[ARRAYIDX]], align 824; CHECK-NEXT: [[ADD24:%.*]] = add nsw i32 [[MUL]], 225; CHECK-NEXT: [[IDXPROM25:%.*]] = sext i32 [[ADD24]] to i6426; CHECK-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 [[IDXPROM25]]27; CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[ARRAYIDX26]], align 828; CHECK-NEXT: [[ARRAYIDX30:%.*]] = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 [[IDXPROM25]]29; CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[ARRAYIDX30]], align 830; CHECK-NEXT: [[ADD31:%.*]] = fadd double [[TMP3]], [[TMP4]]31; CHECK-NEXT: store double [[ADD31]], ptr [[ARRAYIDX26]], align 832; CHECK-NEXT: ret void33;34entry:35 %u.addr = alloca i32, align 436 store i32 %u, ptr %u.addr, align 437 %mul = mul nsw i32 %u, 338 %idxprom = sext i32 %mul to i6439 %arrayidx = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom40 %0 = load double, ptr %arrayidx, align 841 %arrayidx4 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom42 %1 = load double, ptr %arrayidx4, align 843 %add5 = fadd double %0, %144 store double %add5, ptr %arrayidx, align 845 %add11 = add nsw i32 %mul, 146 %idxprom12 = sext i32 %add11 to i6447 %arrayidx13 = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom1248 %2 = load double, ptr %arrayidx13, align 849 %arrayidx17 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom1250 %3 = load double, ptr %arrayidx17, align 851 %add18 = fadd double %2, %352 store double %add18, ptr %arrayidx13, align 853 %add24 = add nsw i32 %mul, 254 %idxprom25 = sext i32 %add24 to i6455 %arrayidx26 = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom2556 %4 = load double, ptr %arrayidx26, align 857 %arrayidx30 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom2558 %5 = load double, ptr %arrayidx30, align 859 %add31 = fadd double %4, %560 store double %add31, ptr %arrayidx26, align 861 ret void62}63 64; SCEV should be able to tell that accesses A[C1 + C2*i], A[C1 + C2*i], ...65; A[C1 + C2*i] are consecutive, if C2 is a power of 2, and C2 > C1 > 0.66; Thus, the following code should be vectorized.67; Function Attrs: nounwind ssp uwtable68define void @foo_2double(i32 %u) {69; CHECK-LABEL: @foo_2double(70; CHECK-NEXT: entry:71; CHECK-NEXT: [[U_ADDR:%.*]] = alloca i32, align 472; CHECK-NEXT: store i32 [[U:%.*]], ptr [[U_ADDR]], align 473; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[U]], 274; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[MUL]] to i6475; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 [[IDXPROM]]76; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 [[IDXPROM]]77; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 878; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAYIDX4]], align 879; CHECK-NEXT: [[TMP2:%.*]] = fadd <2 x double> [[TMP0]], [[TMP1]]80; CHECK-NEXT: store <2 x double> [[TMP2]], ptr [[ARRAYIDX]], align 881; CHECK-NEXT: ret void82;83entry:84 %u.addr = alloca i32, align 485 store i32 %u, ptr %u.addr, align 486 %mul = mul nsw i32 %u, 287 %idxprom = sext i32 %mul to i6488 %arrayidx = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom89 %0 = load double, ptr %arrayidx, align 890 %arrayidx4 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom91 %1 = load double, ptr %arrayidx4, align 892 %add5 = fadd double %0, %193 store double %add5, ptr %arrayidx, align 894 %add11 = add nsw i32 %mul, 195 %idxprom12 = sext i32 %add11 to i6496 %arrayidx13 = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom1297 %2 = load double, ptr %arrayidx13, align 898 %arrayidx17 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom1299 %3 = load double, ptr %arrayidx17, align 8100 %add18 = fadd double %2, %3101 store double %add18, ptr %arrayidx13, align 8102 ret void103}104 105; Similar to the previous test, but with different datatype.106; Function Attrs: nounwind ssp uwtable107define void @foo_4float(i32 %u) {108; CHECK-LABEL: @foo_4float(109; CHECK-NEXT: entry:110; CHECK-NEXT: [[U_ADDR:%.*]] = alloca i32, align 4111; CHECK-NEXT: store i32 [[U:%.*]], ptr [[U_ADDR]], align 4112; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[U]], 4113; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[MUL]] to i64114; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2000 x float], ptr @C, i32 0, i64 [[IDXPROM]]115; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [2000 x float], ptr @D, i32 0, i64 [[IDXPROM]]116; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 4117; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[ARRAYIDX4]], align 4118; CHECK-NEXT: [[TMP2:%.*]] = fadd <4 x float> [[TMP0]], [[TMP1]]119; CHECK-NEXT: store <4 x float> [[TMP2]], ptr [[ARRAYIDX]], align 4120; CHECK-NEXT: ret void121;122entry:123 %u.addr = alloca i32, align 4124 store i32 %u, ptr %u.addr, align 4125 %mul = mul nsw i32 %u, 4126 %idxprom = sext i32 %mul to i64127 %arrayidx = getelementptr inbounds [2000 x float], ptr @C, i32 0, i64 %idxprom128 %0 = load float, ptr %arrayidx, align 4129 %arrayidx4 = getelementptr inbounds [2000 x float], ptr @D, i32 0, i64 %idxprom130 %1 = load float, ptr %arrayidx4, align 4131 %add5 = fadd float %0, %1132 store float %add5, ptr %arrayidx, align 4133 %add11 = add nsw i32 %mul, 1134 %idxprom12 = sext i32 %add11 to i64135 %arrayidx13 = getelementptr inbounds [2000 x float], ptr @C, i32 0, i64 %idxprom12136 %2 = load float, ptr %arrayidx13, align 4137 %arrayidx17 = getelementptr inbounds [2000 x float], ptr @D, i32 0, i64 %idxprom12138 %3 = load float, ptr %arrayidx17, align 4139 %add18 = fadd float %2, %3140 store float %add18, ptr %arrayidx13, align 4141 %add24 = add nsw i32 %mul, 2142 %idxprom25 = sext i32 %add24 to i64143 %arrayidx26 = getelementptr inbounds [2000 x float], ptr @C, i32 0, i64 %idxprom25144 %4 = load float, ptr %arrayidx26, align 4145 %arrayidx30 = getelementptr inbounds [2000 x float], ptr @D, i32 0, i64 %idxprom25146 %5 = load float, ptr %arrayidx30, align 4147 %add31 = fadd float %4, %5148 store float %add31, ptr %arrayidx26, align 4149 %add37 = add nsw i32 %mul, 3150 %idxprom38 = sext i32 %add37 to i64151 %arrayidx39 = getelementptr inbounds [2000 x float], ptr @C, i32 0, i64 %idxprom38152 %6 = load float, ptr %arrayidx39, align 4153 %arrayidx43 = getelementptr inbounds [2000 x float], ptr @D, i32 0, i64 %idxprom38154 %7 = load float, ptr %arrayidx43, align 4155 %add44 = fadd float %6, %7156 store float %add44, ptr %arrayidx39, align 4157 ret void158}159 160; Similar to the previous tests, but now we are dealing with AddRec SCEV.161; Function Attrs: nounwind ssp uwtable162define i32 @foo_loop(ptr %A, i32 %n) {163; CHECK-LABEL: @foo_loop(164; CHECK-NEXT: entry:165; CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8166; CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4167; CHECK-NEXT: [[SUM:%.*]] = alloca double, align 8168; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4169; CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8170; CHECK-NEXT: store i32 [[N:%.*]], ptr [[N_ADDR]], align 4171; CHECK-NEXT: store double 0.000000e+00, ptr [[SUM]], align 8172; CHECK-NEXT: store i32 0, ptr [[I]], align 4173; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[N]]174; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END:%.*]]175; CHECK: for.body.lr.ph:176; CHECK-NEXT: br label [[FOR_BODY:%.*]]177; CHECK: for.body:178; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]179; CHECK-NEXT: [[TMP1:%.*]] = phi double [ 0.000000e+00, [[FOR_BODY_LR_PH]] ], [ [[ADD7:%.*]], [[FOR_BODY]] ]180; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP0]], 2181; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[MUL]] to i64182; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[IDXPROM]]183; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8184; CHECK-NEXT: [[TMP3:%.*]] = fmul <2 x double> <double 7.000000e+00, double 7.000000e+00>, [[TMP2]]185; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[TMP3]], i32 0186; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[TMP3]], i32 1187; CHECK-NEXT: [[ADD6:%.*]] = fadd double [[TMP4]], [[TMP5]]188; CHECK-NEXT: [[ADD7]] = fadd double [[TMP1]], [[ADD6]]189; CHECK-NEXT: store double [[ADD7]], ptr [[SUM]], align 8190; CHECK-NEXT: [[INC]] = add nsw i32 [[TMP0]], 1191; CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4192; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[N]]193; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_CRIT_EDGE:%.*]]194; CHECK: for.cond.for.end_crit_edge:195; CHECK-NEXT: [[SPLIT:%.*]] = phi double [ [[ADD7]], [[FOR_BODY]] ]196; CHECK-NEXT: br label [[FOR_END]]197; CHECK: for.end:198; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi double [ [[SPLIT]], [[FOR_COND_FOR_END_CRIT_EDGE]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]199; CHECK-NEXT: [[CONV:%.*]] = fptosi double [[DOTLCSSA]] to i32200; CHECK-NEXT: ret i32 [[CONV]]201;202entry:203 %A.addr = alloca ptr, align 8204 %n.addr = alloca i32, align 4205 %sum = alloca double, align 8206 %i = alloca i32, align 4207 store ptr %A, ptr %A.addr, align 8208 store i32 %n, ptr %n.addr, align 4209 store double 0.000000e+00, ptr %sum, align 8210 store i32 0, ptr %i, align 4211 %cmp1 = icmp slt i32 0, %n212 br i1 %cmp1, label %for.body.lr.ph, label %for.end213 214for.body.lr.ph: ; preds = %entry215 br label %for.body216 217for.body: ; preds = %for.body.lr.ph, %for.body218 %0 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]219 %1 = phi double [ 0.000000e+00, %for.body.lr.ph ], [ %add7, %for.body ]220 %mul = mul nsw i32 %0, 2221 %idxprom = sext i32 %mul to i64222 %arrayidx = getelementptr inbounds double, ptr %A, i64 %idxprom223 %2 = load double, ptr %arrayidx, align 8224 %mul1 = fmul double 7.000000e+00, %2225 %add = add nsw i32 %mul, 1226 %idxprom3 = sext i32 %add to i64227 %arrayidx4 = getelementptr inbounds double, ptr %A, i64 %idxprom3228 %3 = load double, ptr %arrayidx4, align 8229 %mul5 = fmul double 7.000000e+00, %3230 %add6 = fadd double %mul1, %mul5231 %add7 = fadd double %1, %add6232 store double %add7, ptr %sum, align 8233 %inc = add nsw i32 %0, 1234 store i32 %inc, ptr %i, align 4235 %cmp = icmp slt i32 %inc, %n236 br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge237 238for.cond.for.end_crit_edge: ; preds = %for.body239 %split = phi double [ %add7, %for.body ]240 br label %for.end241 242for.end: ; preds = %for.cond.for.end_crit_edge, %entry243 %.lcssa = phi double [ %split, %for.cond.for.end_crit_edge ], [ 0.000000e+00, %entry ]244 %conv = fptosi double %.lcssa to i32245 ret i32 %conv246}247 248; Similar to foo_2double but with a non-power-of-2 factor and potential249; wrapping (both indices wrap or both don't in the same time)250; Function Attrs: nounwind ssp uwtable251define void @foo_2double_non_power_of_2(i32 %u) {252; CHECK-LABEL: @foo_2double_non_power_of_2(253; CHECK-NEXT: entry:254; CHECK-NEXT: [[U_ADDR:%.*]] = alloca i32, align 4255; CHECK-NEXT: store i32 [[U:%.*]], ptr [[U_ADDR]], align 4256; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[U]], 6257; CHECK-NEXT: [[ADD6:%.*]] = add i32 [[MUL]], 6258; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD6]] to i64259; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 [[IDXPROM]]260; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 [[IDXPROM]]261; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8262; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAYIDX4]], align 8263; CHECK-NEXT: [[TMP2:%.*]] = fadd <2 x double> [[TMP0]], [[TMP1]]264; CHECK-NEXT: store <2 x double> [[TMP2]], ptr [[ARRAYIDX]], align 8265; CHECK-NEXT: ret void266;267entry:268 %u.addr = alloca i32, align 4269 store i32 %u, ptr %u.addr, align 4270 %mul = mul i32 %u, 6271 %add6 = add i32 %mul, 6272 %idxprom = sext i32 %add6 to i64273 %arrayidx = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom274 %0 = load double, ptr %arrayidx, align 8275 %arrayidx4 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom276 %1 = load double, ptr %arrayidx4, align 8277 %add5 = fadd double %0, %1278 store double %add5, ptr %arrayidx, align 8279 %add7 = add i32 %mul, 7280 %idxprom12 = sext i32 %add7 to i64281 %arrayidx13 = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom12282 %2 = load double, ptr %arrayidx13, align 8283 %arrayidx17 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom12284 %3 = load double, ptr %arrayidx17, align 8285 %add18 = fadd double %2, %3286 store double %add18, ptr %arrayidx13, align 8287 ret void288}289 290; Similar to foo_2double_non_power_of_2 but with zext's instead of sext's291; Function Attrs: nounwind ssp uwtable292define void @foo_2double_non_power_of_2_zext(i32 %u) {293; CHECK-LABEL: @foo_2double_non_power_of_2_zext(294; CHECK-NEXT: entry:295; CHECK-NEXT: [[U_ADDR:%.*]] = alloca i32, align 4296; CHECK-NEXT: store i32 [[U:%.*]], ptr [[U_ADDR]], align 4297; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[U]], 6298; CHECK-NEXT: [[ADD6:%.*]] = add i32 [[MUL]], 6299; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[ADD6]] to i64300; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 [[IDXPROM]]301; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 [[IDXPROM]]302; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8303; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[ARRAYIDX4]], align 8304; CHECK-NEXT: [[TMP2:%.*]] = fadd <2 x double> [[TMP0]], [[TMP1]]305; CHECK-NEXT: store <2 x double> [[TMP2]], ptr [[ARRAYIDX]], align 8306; CHECK-NEXT: ret void307;308entry:309 %u.addr = alloca i32, align 4310 store i32 %u, ptr %u.addr, align 4311 %mul = mul i32 %u, 6312 %add6 = add i32 %mul, 6313 %idxprom = zext i32 %add6 to i64314 %arrayidx = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom315 %0 = load double, ptr %arrayidx, align 8316 %arrayidx4 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom317 %1 = load double, ptr %arrayidx4, align 8318 %add5 = fadd double %0, %1319 store double %add5, ptr %arrayidx, align 8320 %add7 = add i32 %mul, 7321 %idxprom12 = zext i32 %add7 to i64322 %arrayidx13 = getelementptr inbounds [2000 x double], ptr @A, i32 0, i64 %idxprom12323 %2 = load double, ptr %arrayidx13, align 8324 %arrayidx17 = getelementptr inbounds [2000 x double], ptr @B, i32 0, i64 %idxprom12325 %3 = load double, ptr %arrayidx17, align 8326 %add18 = fadd double %2, %3327 store double %add18, ptr %arrayidx13, align 8328 ret void329}330 331; Similar to foo_2double_non_power_of_2, but now we are dealing with AddRec SCEV.332; Alternatively, this is like foo_loop, but with a non-power-of-2 factor and333; potential wrapping (both indices wrap or both don't in the same time)334; Function Attrs: nounwind ssp uwtable335define i32 @foo_loop_non_power_of_2(ptr %A, i32 %n) {336; CHECK-LABEL: @foo_loop_non_power_of_2(337; CHECK-NEXT: entry:338; CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8339; CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4340; CHECK-NEXT: [[SUM:%.*]] = alloca double, align 8341; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4342; CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8343; CHECK-NEXT: store i32 [[N:%.*]], ptr [[N_ADDR]], align 4344; CHECK-NEXT: store double 0.000000e+00, ptr [[SUM]], align 8345; CHECK-NEXT: store i32 0, ptr [[I]], align 4346; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[N]]347; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END:%.*]]348; CHECK: for.body.lr.ph:349; CHECK-NEXT: br label [[FOR_BODY:%.*]]350; CHECK: for.body:351; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]352; CHECK-NEXT: [[TMP1:%.*]] = phi double [ 0.000000e+00, [[FOR_BODY_LR_PH]] ], [ [[ADD7:%.*]], [[FOR_BODY]] ]353; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP0]], 12354; CHECK-NEXT: [[ADD_5:%.*]] = add i32 [[MUL]], 5355; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[ADD_5]] to i64356; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[IDXPROM]]357; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8358; CHECK-NEXT: [[TMP3:%.*]] = fmul <2 x double> <double 7.000000e+00, double 7.000000e+00>, [[TMP2]]359; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[TMP3]], i32 0360; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[TMP3]], i32 1361; CHECK-NEXT: [[ADD6:%.*]] = fadd double [[TMP4]], [[TMP5]]362; CHECK-NEXT: [[ADD7]] = fadd double [[TMP1]], [[ADD6]]363; CHECK-NEXT: store double [[ADD7]], ptr [[SUM]], align 8364; CHECK-NEXT: [[INC]] = add i32 [[TMP0]], 1365; CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4366; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[N]]367; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_CRIT_EDGE:%.*]]368; CHECK: for.cond.for.end_crit_edge:369; CHECK-NEXT: [[SPLIT:%.*]] = phi double [ [[ADD7]], [[FOR_BODY]] ]370; CHECK-NEXT: br label [[FOR_END]]371; CHECK: for.end:372; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi double [ [[SPLIT]], [[FOR_COND_FOR_END_CRIT_EDGE]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]373; CHECK-NEXT: [[CONV:%.*]] = fptosi double [[DOTLCSSA]] to i32374; CHECK-NEXT: ret i32 [[CONV]]375;376entry:377 %A.addr = alloca ptr, align 8378 %n.addr = alloca i32, align 4379 %sum = alloca double, align 8380 %i = alloca i32, align 4381 store ptr %A, ptr %A.addr, align 8382 store i32 %n, ptr %n.addr, align 4383 store double 0.000000e+00, ptr %sum, align 8384 store i32 0, ptr %i, align 4385 %cmp1 = icmp slt i32 0, %n386 br i1 %cmp1, label %for.body.lr.ph, label %for.end387 388for.body.lr.ph: ; preds = %entry389 br label %for.body390 391for.body: ; preds = %for.body.lr.ph, %for.body392 %0 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]393 %1 = phi double [ 0.000000e+00, %for.body.lr.ph ], [ %add7, %for.body ]394 %mul = mul i32 %0, 12395 %add.5 = add i32 %mul, 5396 %idxprom = sext i32 %add.5 to i64397 %arrayidx = getelementptr inbounds double, ptr %A, i64 %idxprom398 %2 = load double, ptr %arrayidx, align 8399 %mul1 = fmul double 7.000000e+00, %2400 %add.6 = add i32 %mul, 6401 %idxprom3 = sext i32 %add.6 to i64402 %arrayidx4 = getelementptr inbounds double, ptr %A, i64 %idxprom3403 %3 = load double, ptr %arrayidx4, align 8404 %mul5 = fmul double 7.000000e+00, %3405 %add6 = fadd double %mul1, %mul5406 %add7 = fadd double %1, %add6407 store double %add7, ptr %sum, align 8408 %inc = add i32 %0, 1409 store i32 %inc, ptr %i, align 4410 %cmp = icmp slt i32 %inc, %n411 br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge412 413for.cond.for.end_crit_edge: ; preds = %for.body414 %split = phi double [ %add7, %for.body ]415 br label %for.end416 417for.end: ; preds = %for.cond.for.end_crit_edge, %entry418 %.lcssa = phi double [ %split, %for.cond.for.end_crit_edge ], [ 0.000000e+00, %entry ]419 %conv = fptosi double %.lcssa to i32420 ret i32 %conv421}422 423; This is generated by `clang -std=c11 -Wpedantic -Wall -O3 main.c -S -o - -emit-llvm`424; with !{!"clang version 7.0.0 (trunk 337339) (llvm/trunk 337344)"} and stripping off425; the !tbaa metadata nodes to fit the rest of the test file, where `cat main.c` is:426;427; double bar(ptr a, unsigned n) {428; double x = 0.0;429; double y = 0.0;430; for (unsigned i = 0; i < n; i += 2) {431; x += a[i];432; y += a[i + 1];433; }434; return x * y;435; }436;437; The resulting IR is similar to @foo_loop, but with zext's instead of sext's.438;439; Make sure we are able to vectorize this from now on:440;441define double @bar(ptr nocapture readonly %a, i32 %n) local_unnamed_addr {442; CHECK-X86-LABEL: @bar(443; CHECK-X86-NEXT: entry:444; CHECK-X86-NEXT: [[CMP15:%.*]] = icmp eq i32 [[N:%.*]], 0445; CHECK-X86-NEXT: br i1 [[CMP15]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]]446; CHECK-X86: for.cond.cleanup:447; CHECK-X86-NEXT: [[TMP0:%.*]] = phi <2 x double> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[TMP5:%.*]], [[FOR_BODY]] ]448; CHECK-X86-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[TMP0]], i32 0449; CHECK-X86-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP0]], i32 1450; CHECK-X86-NEXT: [[MUL:%.*]] = fmul double [[TMP1]], [[TMP2]]451; CHECK-X86-NEXT: ret double [[MUL]]452; CHECK-X86: for.body:453; CHECK-X86-NEXT: [[I_018:%.*]] = phi i32 [ [[ADD5:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]454; CHECK-X86-NEXT: [[TMP3:%.*]] = phi <2 x double> [ [[TMP5]], [[FOR_BODY]] ], [ zeroinitializer, [[ENTRY]] ]455; CHECK-X86-NEXT: [[IDXPROM:%.*]] = zext i32 [[I_018]] to i64456; CHECK-X86-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i64 [[IDXPROM]]457; CHECK-X86-NEXT: [[TMP4:%.*]] = load <2 x double>, ptr [[ARRAYIDX]], align 8458; CHECK-X86-NEXT: [[TMP5]] = fadd <2 x double> [[TMP3]], [[TMP4]]459; CHECK-X86-NEXT: [[ADD5]] = add i32 [[I_018]], 2460; CHECK-X86-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD5]], [[N]]461; CHECK-X86-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]462;463 464; CHECK-AARCH64-LABEL: @bar(465; CHECK-AARCH64-NEXT: entry:466; CHECK-AARCH64-NEXT: [[CMP15:%.*]] = icmp eq i32 [[N:%.*]], 0467; CHECK-AARCH64-NEXT: br i1 [[CMP15]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]]468; CHECK-AARCH64: for.cond.cleanup:469; CHECK-AARCH64-NEXT: [[X_0_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]470; CHECK-AARCH64-NEXT: [[Y_0_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD4:%.*]], [[FOR_BODY]] ]471; CHECK-AARCH64-NEXT: [[MUL:%.*]] = fmul double [[X_0_LCSSA]], [[Y_0_LCSSA]]472; CHECK-AARCH64-NEXT: ret double [[MUL]]473; CHECK-AARCH64: for.body:474; CHECK-AARCH64-NEXT: [[I_018:%.*]] = phi i32 [ [[ADD5:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ]475; CHECK-AARCH64-NEXT: [[Y_017:%.*]] = phi double [ [[ADD4]], [[FOR_BODY]] ], [ 0.000000e+00, [[ENTRY]] ]476; CHECK-AARCH64-NEXT: [[X_016:%.*]] = phi double [ [[ADD]], [[FOR_BODY]] ], [ 0.000000e+00, [[ENTRY]] ]477; CHECK-AARCH64-NEXT: [[IDXPROM:%.*]] = zext i32 [[I_018]] to i64478; CHECK-AARCH64-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[A:%.*]], i64 [[IDXPROM]]479; CHECK-AARCH64-NEXT: [[TMP0:%.*]] = load double, ptr [[ARRAYIDX]], align 8480; CHECK-AARCH64-NEXT: [[ADD]] = fadd double [[X_016]], [[TMP0]]481; CHECK-AARCH64-NEXT: [[ADD1:%.*]] = or disjoint i32 [[I_018]], 1482; CHECK-AARCH64-NEXT: [[IDXPROM2:%.*]] = zext i32 [[ADD1]] to i64483; CHECK-AARCH64-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[IDXPROM2]]484; CHECK-AARCH64-NEXT: [[TMP1:%.*]] = load double, ptr [[ARRAYIDX3]], align 8485; CHECK-AARCH64-NEXT: [[ADD4]] = fadd double [[Y_017]], [[TMP1]]486; CHECK-AARCH64-NEXT: [[ADD5]] = add i32 [[I_018]], 2487; CHECK-AARCH64-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD5]], [[N]]488; CHECK-AARCH64-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]489;490 491entry:492 %cmp15 = icmp eq i32 %n, 0493 br i1 %cmp15, label %for.cond.cleanup, label %for.body494 495for.cond.cleanup: ; preds = %for.body, %entry496 %x.0.lcssa = phi double [ 0.000000e+00, %entry ], [ %add, %for.body ]497 %y.0.lcssa = phi double [ 0.000000e+00, %entry ], [ %add4, %for.body ]498 %mul = fmul double %x.0.lcssa, %y.0.lcssa499 ret double %mul500 501for.body: ; preds = %entry, %for.body502 %i.018 = phi i32 [ %add5, %for.body ], [ 0, %entry ]503 %y.017 = phi double [ %add4, %for.body ], [ 0.000000e+00, %entry ]504 %x.016 = phi double [ %add, %for.body ], [ 0.000000e+00, %entry ]505 %idxprom = zext i32 %i.018 to i64506 %arrayidx = getelementptr inbounds double, ptr %a, i64 %idxprom507 %0 = load double, ptr %arrayidx, align 8508 %add = fadd double %x.016, %0509 %add1 = or disjoint i32 %i.018, 1510 %idxprom2 = zext i32 %add1 to i64511 %arrayidx3 = getelementptr inbounds double, ptr %a, i64 %idxprom2512 %1 = load double, ptr %arrayidx3, align 8513 %add4 = fadd double %y.017, %1514 %add5 = add i32 %i.018, 2515 %cmp = icmp ult i32 %add5, %n516 br i1 %cmp, label %for.body, label %for.cond.cleanup517}518 519; Globals/constant expressions are not normal constants.520; They should not be treated as the usual vectorization candidates.521 522@g1 = external global i32, align 4523@g2 = external global i32, align 4524 525define void @PR33958(ptr nocapture %p) {526; CHECK-LABEL: @PR33958(527; CHECK-NEXT: store ptr @g1, ptr [[P:%.*]], align 8528; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds ptr, ptr [[P]], i64 1529; CHECK-NEXT: store ptr @g2, ptr [[ARRAYIDX1]], align 8530; CHECK-NEXT: ret void531;532 store ptr @g1, ptr %p, align 8533 %arrayidx1 = getelementptr inbounds ptr, ptr %p, i64 1534 store ptr @g2, ptr %arrayidx1, align 8535 ret void536}537 538define void @store_constant_expression(ptr %p) {539; CHECK-LABEL: @store_constant_expression(540; CHECK-NEXT: store i64 ptrtoint (ptr @g1 to i64), ptr [[P:%.*]], align 8541; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 1542; CHECK-NEXT: store i64 ptrtoint (ptr @g2 to i64), ptr [[ARRAYIDX1]], align 8543; CHECK-NEXT: ret void544;545 store i64 ptrtoint (ptr @g1 to i64), ptr %p, align 8546 %arrayidx1 = getelementptr inbounds i64, ptr %p, i64 1547 store i64 ptrtoint (ptr @g2 to i64), ptr %arrayidx1, align 8548 ret void549}550 551!llvm.ident = !{!0}552 553!0 = !{!"clang version 3.5.0 "}554