// induction variable and step. Otherwise, derive these values from the
// induction descriptor.
if (!VectorizedIV || NeedsScalarIV) {
+ ScalarIV = Induction;
+ if (IV != OldInduction) {
+ ScalarIV = IV->getType()->isIntegerTy()
+ ? Builder.CreateSExtOrTrunc(Induction, IV->getType())
+ : Builder.CreateCast(Instruction::SIToFP, Induction,
+ IV->getType());
+ ScalarIV = ID.transform(Builder, ScalarIV, PSE.getSE(), DL);
+ ScalarIV->setName("offset.idx");
+ }
if (Trunc) {
auto *TruncType = cast<IntegerType>(Trunc->getType());
assert(Step->getType()->isIntegerTy() &&
"Truncation requires an integer step");
- ScalarIV = Builder.CreateCast(Instruction::Trunc, Induction, TruncType);
+ ScalarIV = Builder.CreateTrunc(ScalarIV, TruncType);
Step = Builder.CreateTrunc(Step, TruncType);
- } else {
- ScalarIV = Induction;
- if (IV != OldInduction) {
- ScalarIV = IV->getType()->isIntegerTy()
- ? Builder.CreateSExtOrTrunc(ScalarIV, IV->getType())
- : Builder.CreateCast(Instruction::SIToFP, Induction,
- IV->getType());
- ScalarIV = ID.transform(Builder, ScalarIV, PSE.getSE(), DL);
- ScalarIV->setName("offset.idx");
- }
}
}
for.end:
ret void
}
+
+; PR32419. Ensure we transform truncated non-primary induction variables. In
+; the test case below we replace %tmp1 with a new induction variable. Because
+; the truncated value is non-primary, we must compute an offset from the
+; primary induction variable.
+;
+; CHECK-LABEL: @PR32419(
+; CHECK: vector.body:
+; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %[[PRED_UREM_CONTINUE4:.*]] ]
+; CHECK: [[OFFSET_IDX:%.*]] = add i32 -20, [[INDEX]]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[OFFSET_IDX]] to i16
+; CHECK: [[TMP8:%.*]] = add i16 [[TMP1]], 0
+; CHECK-NEXT: [[TMP9:%.*]] = urem i16 %b, [[TMP8]]
+; CHECK: [[TMP15:%.*]] = add i16 [[TMP1]], 1
+; CHECK-NEXT: [[TMP16:%.*]] = urem i16 %b, [[TMP15]]
+; CHECK: [[PRED_UREM_CONTINUE4]]:
+; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body
+;
+define i32 @PR32419(i32 %a, i16 %b) {
+entry:
+ br label %for.body
+
+for.body:
+ %i = phi i32 [ -20, %entry ], [ %i.next, %for.inc ]
+ %tmp0 = phi i32 [ %a, %entry ], [ %tmp6, %for.inc ]
+ %tmp1 = trunc i32 %i to i16
+ %tmp2 = icmp eq i16 %tmp1, 0
+ br i1 %tmp2, label %for.inc, label %for.cond
+
+for.cond:
+ %tmp3 = urem i16 %b, %tmp1
+ br label %for.inc
+
+for.inc:
+ %tmp4 = phi i16 [ %tmp3, %for.cond ], [ 0, %for.body ]
+ %tmp5 = sext i16 %tmp4 to i32
+ %tmp6 = or i32 %tmp0, %tmp5
+ %i.next = add nsw i32 %i, 1
+ %cond = icmp eq i32 %i.next, 0
+ br i1 %cond, label %for.end, label %for.body
+
+for.end:
+ %tmp7 = phi i32 [ %tmp6, %for.inc ]
+ ret i32 %tmp7
+}