[Analysis][LoopVectorize] do not form reductions of pointers

This is a fix for https://llvm.org/PR49215 either before/after
we make a verifier enhancement for vector reductions with D96904.

I'm not sure what the current thinking is for pointer math/logic
in IR. We allow icmp on pointer values. Therefore, we match min/max
patterns, so without this patch, the vectorizer could form a vector
reduction from that sequence.

But the LangRef definitions for min/max and vector reduction
intrinsics do not allow pointer types:
https://llvm.org/docs/LangRef.html#llvm-smax-intrinsic
https://llvm.org/docs/LangRef.html#llvm-vector-reduce-umax-intrinsic

So we would crash/assert at some point - either in IR verification,
in the cost model, or in codegen. If we do want to allow this kind
of transform, we will need to update the LangRef and all of those
parts of the compiler.

Differential Revision: https://reviews.llvm.org/D97047
This commit is contained in:
Sanjay Patel 2021-02-19 09:06:05 -05:00
parent 91c472c86c
commit 5b250a27ec
2 changed files with 44 additions and 1 deletions

View File

@ -243,11 +243,14 @@ bool RecurrenceDescriptor::AddReductionVar(PHINode *Phi, RecurKind Kind,
if (RecurrenceType->isFloatingPointTy()) {
if (!isFloatingPointRecurrenceKind(Kind))
return false;
} else {
} else if (RecurrenceType->isIntegerTy()) {
if (!isIntegerRecurrenceKind(Kind))
return false;
if (isArithmeticRecurrenceKind(Kind))
Start = lookThroughAnd(Phi, RecurrenceType, VisitedInsts, CastInsts);
} else {
// Pointer min/max may exist, but it is not supported as a reduction op.
return false;
}
Worklist.push_back(Start);

View File

@ -0,0 +1,40 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -loop-vectorize -force-vector-width=4 -S | FileCheck %s
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
; Reductions of pointer types are not supported.
define void @PR49215(i32* %p, i32* %q) {
; CHECK-LABEL: @PR49215(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[G:%.*]] = phi i32* [ [[P:%.*]], [[ENTRY]] ], [ [[UMIN:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32* [[Q:%.*]], [[G]]
; CHECK-NEXT: [[UMIN]] = select i1 [[CMP2]], i32* [[Q]], i32* [[G]]
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], undef
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOPEXIT:%.*]], label [[FOR_BODY]]
; CHECK: loopexit:
; CHECK-NEXT: [[UMIN_LCSSA:%.*]] = phi i32* [ [[UMIN]], [[FOR_BODY]] ]
; CHECK-NEXT: [[PHI_CAST:%.*]] = ptrtoint i32* [[UMIN_LCSSA]] to i64
; CHECK-NEXT: ret void
;
entry:
br label %for.body
for.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
%g = phi i32* [ %p, %entry ], [ %umin, %for.body ]
%cmp2 = icmp ult i32* %q, %g
%umin = select i1 %cmp2, i32* %q, i32* %g
%iv.next = add nuw nsw i64 %iv, 1
%exitcond = icmp eq i64 %iv.next, undef
br i1 %exitcond, label %loopexit, label %for.body
loopexit:
%phi.cast = ptrtoint i32* %umin to i64
ret void
}