From 86d6f7e90a1deab93e357b8f356e29d4a24fa3ac Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Sun, 10 Jan 2021 12:26:24 -0800 Subject: [PATCH] Precommit tests requested for D93725 --- .../first-order-recurrence-complex.ll | 91 +++++++++++++ .../Transforms/LoopVectorize/loop-form.ll | 123 ++++++++++++++++++ 2 files changed, 214 insertions(+) diff --git a/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll b/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll index 208e1a219be8..ef3d3e659e5a 100644 --- a/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll +++ b/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll @@ -432,3 +432,94 @@ loop.latch: ; preds = %if.then122, %for.b exit: ret void } + +; A recurrence in a multiple exit loop. +define i16 @multiple_exit(i16* %p, i32 %n) { +; CHECK-LABEL: @multiple_exit( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ] +; CHECK-NEXT: [[REC:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[REC_NEXT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64 +; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, i16* [[P:%.*]], i64 [[IPROM]] +; CHECK-NEXT: [[REC_NEXT]] = load i16, i16* [[B]], align 2 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]] +; CHECK: for.body: +; CHECK-NEXT: store i16 [[REC]], i16* [[B]], align 4 +; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1 +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096 +; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[REC_LCSSA:%.*]] = phi i16 [ [[REC]], [[FOR_BODY]] ], [ [[REC]], [[FOR_COND]] ] +; CHECK-NEXT: ret i16 [[REC_LCSSA]] +; +entry: + br label %for.cond + +for.cond: + %i = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %rec = phi i16 [0, %entry], [ %rec.next, %for.body ] + %iprom = sext i32 %i to i64 + %b = getelementptr inbounds i16, i16* %p, i64 %iprom + %rec.next = load i16, i16* %b + %cmp = icmp slt i32 %i, %n + br i1 %cmp, label %for.body, label %if.end + +for.body: + store i16 %rec , i16* %b, align 4 + %inc = add nsw i32 %i, 1 + %cmp2 = icmp slt i32 %i, 2096 + br i1 %cmp2, label %for.cond, label %if.end + +if.end: + ret i16 %rec +} + + +; A multiple exit case where one of the exiting edges involves a value +; from the recurrence and one does not. +define i16 @multiple_exit2(i16* %p, i32 %n) { +; CHECK-LABEL: @multiple_exit2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ] +; CHECK-NEXT: [[REC:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[REC_NEXT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IPROM:%.*]] = sext i32 [[I]] to i64 +; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i16, i16* [[P:%.*]], i64 [[IPROM]] +; CHECK-NEXT: [[REC_NEXT]] = load i16, i16* [[B]], align 2 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I]], [[N:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[IF_END:%.*]] +; CHECK: for.body: +; CHECK-NEXT: store i16 [[REC]], i16* [[B]], align 4 +; CHECK-NEXT: [[INC]] = add nsw i32 [[I]], 1 +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[I]], 2096 +; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[REC_LCSSA:%.*]] = phi i16 [ [[REC]], [[FOR_COND]] ], [ 10, [[FOR_BODY]] ] +; CHECK-NEXT: ret i16 [[REC_LCSSA]] +; +entry: + br label %for.cond + +for.cond: + %i = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %rec = phi i16 [0, %entry], [ %rec.next, %for.body ] + %iprom = sext i32 %i to i64 + %b = getelementptr inbounds i16, i16* %p, i64 %iprom + %rec.next = load i16, i16* %b + %cmp = icmp slt i32 %i, %n + br i1 %cmp, label %for.body, label %if.end + +for.body: + store i16 %rec , i16* %b, align 4 + %inc = add nsw i32 %i, 1 + %cmp2 = icmp slt i32 %i, 2096 + br i1 %cmp2, label %for.cond, label %if.end + +if.end: + %rec.lcssa = phi i16 [ %rec, %for.cond ], [ 10, %for.body ] + ret i16 %rec.lcssa +} diff --git a/llvm/test/Transforms/LoopVectorize/loop-form.ll b/llvm/test/Transforms/LoopVectorize/loop-form.ll index f93c038de6bb..bf94505aec2c 100644 --- a/llvm/test/Transforms/LoopVectorize/loop-form.ll +++ b/llvm/test/Transforms/LoopVectorize/loop-form.ll @@ -869,3 +869,126 @@ loop.latch: exit: ret void } + +define i32 @reduction(i32* %addr) { +; CHECK-LABEL: @reduction( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[ADDR:%.*]], i64 [[IV]] +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[GEP]], align 4 +; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND2_NOT:%.*]] = icmp eq i64 [[IV]], 400 +; CHECK-NEXT: br i1 [[EXITCOND2_NOT]], label [[EXIT]], label [[LOOP_HEADER]] +; CHECK: exit: +; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ 0, [[LOOP_HEADER]] ], [ [[ACCUM_NEXT]], [[LOOP_LATCH]] ] +; CHECK-NEXT: ret i32 [[LCSSA]] +; +; TAILFOLD-LABEL: @reduction( +; TAILFOLD-NEXT: entry: +; TAILFOLD-NEXT: br label [[LOOP_HEADER:%.*]] +; TAILFOLD: loop.header: +; TAILFOLD-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; TAILFOLD-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ] +; TAILFOLD-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[ADDR:%.*]], i64 [[IV]] +; TAILFOLD-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200 +; TAILFOLD-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] +; TAILFOLD: loop.latch: +; TAILFOLD-NEXT: [[TMP0:%.*]] = load i32, i32* [[GEP]], align 4 +; TAILFOLD-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]] +; TAILFOLD-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; TAILFOLD-NEXT: [[EXITCOND2_NOT:%.*]] = icmp eq i64 [[IV]], 400 +; TAILFOLD-NEXT: br i1 [[EXITCOND2_NOT]], label [[EXIT]], label [[LOOP_HEADER]] +; TAILFOLD: exit: +; TAILFOLD-NEXT: [[LCSSA:%.*]] = phi i32 [ 0, [[LOOP_HEADER]] ], [ [[ACCUM_NEXT]], [[LOOP_LATCH]] ] +; TAILFOLD-NEXT: ret i32 [[LCSSA]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %accum = phi i32 [0, %entry], [%accum.next, %loop.latch] + %gep = getelementptr i32, i32* %addr, i64 %iv + %exitcond.not = icmp eq i64 %iv, 200 + br i1 %exitcond.not, label %exit, label %loop.latch + +loop.latch: + %0 = load i32, i32* %gep, align 4 + %accum.next = add i32 %accum, %0 + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond2.not = icmp eq i64 %iv, 400 + br i1 %exitcond2.not, label %exit, label %loop.header + +exit: + %lcssa = phi i32 [0, %loop.header], [%accum.next, %loop.latch] + ret i32 %lcssa +} + +; TODO: The current definition of reduction is too strict, we can vectorize +; this. There's an analogous single exit case where we extract the N-1 +; value of the reduction that we can also handle. If we fix the later, the +; multiple exit case probably falls out. +define i32 @reduction2(i32* %addr) { +; CHECK-LABEL: @reduction2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[ADDR:%.*]], i64 [[IV]] +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[GEP]], align 4 +; CHECK-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: br label [[LOOP_HEADER]] +; CHECK: exit: +; CHECK-NEXT: [[ACCUM_LCSSA:%.*]] = phi i32 [ [[ACCUM]], [[LOOP_HEADER]] ] +; CHECK-NEXT: ret i32 [[ACCUM_LCSSA]] +; +; TAILFOLD-LABEL: @reduction2( +; TAILFOLD-NEXT: entry: +; TAILFOLD-NEXT: br label [[LOOP_HEADER:%.*]] +; TAILFOLD: loop.header: +; TAILFOLD-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; TAILFOLD-NEXT: [[ACCUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACCUM_NEXT:%.*]], [[LOOP_LATCH]] ] +; TAILFOLD-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[ADDR:%.*]], i64 [[IV]] +; TAILFOLD-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV]], 200 +; TAILFOLD-NEXT: br i1 [[EXITCOND_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] +; TAILFOLD: loop.latch: +; TAILFOLD-NEXT: [[TMP0:%.*]] = load i32, i32* [[GEP]], align 4 +; TAILFOLD-NEXT: [[ACCUM_NEXT]] = add i32 [[ACCUM]], [[TMP0]] +; TAILFOLD-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; TAILFOLD-NEXT: br label [[LOOP_HEADER]] +; TAILFOLD: exit: +; TAILFOLD-NEXT: [[ACCUM_LCSSA:%.*]] = phi i32 [ [[ACCUM]], [[LOOP_HEADER]] ] +; TAILFOLD-NEXT: ret i32 [[ACCUM_LCSSA]] +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %accum = phi i32 [0, %entry], [%accum.next, %loop.latch] + %gep = getelementptr i32, i32* %addr, i64 %iv + %exitcond.not = icmp eq i64 %iv, 200 + br i1 %exitcond.not, label %exit, label %loop.latch + +loop.latch: + %0 = load i32, i32* %gep, align 4 + %accum.next = add i32 %accum, %0 + %iv.next = add nuw nsw i64 %iv, 1 + br label %loop.header + +exit: + ret i32 %accum +} +