Check that the elements of an array have the same size

At the moment we assume that only elements of identical size are stored/loaded
to a certain base pointer. This patch adds logic to the scop detection to verify
this.

Differential Revision: http://reviews.llvm.org/D5329

llvm-svn: 217727
This commit is contained in:
Tobias Grosser 2014-09-13 14:47:40 +00:00
parent 0bd147da17
commit bcd4efffa7
4 changed files with 119 additions and 3 deletions

View File

@ -86,6 +86,7 @@ enum RejectReasonKind {
rrkUndefBasePtr,
rrkVariantBasePtr,
rrkNonAffineAccess,
rrkDifferentElementSize,
rrkLastAffFunc,
// IndVar
@ -514,6 +515,30 @@ public:
//@}
};
//===----------------------------------------------------------------------===//
/// @brief Report array accesses with differing element size.
class ReportDifferentArrayElementSize : public ReportAffFunc {
//===--------------------------------------------------------------------===//
// The base pointer of the memory access.
const Value *BaseValue;
public:
ReportDifferentArrayElementSize(const Instruction *Inst, const Value *V)
: ReportAffFunc(rrkDifferentElementSize, Inst), BaseValue(V) {}
/// @name LLVM-RTTI interface
//@{
static bool classof(const RejectReason *RR);
//@}
/// @name RejectReason interface
//@{
virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override;
//@}
};
//===----------------------------------------------------------------------===//
/// @brief Base class for reject reasons related to induction variables.
///

View File

@ -433,6 +433,15 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
const SCEV *Size = SE->getElementSize(&Inst);
if (Context.ElementSize.count(BasePointer)) {
if (Context.ElementSize[BasePointer] != Size)
return invalid<ReportDifferentArrayElementSize>(Context, /*Assert=*/true,
&Inst, BaseValue);
} else {
Context.ElementSize[BasePointer] = Size;
}
if (AllowNonAffine) {
// Do not check whether AccessFunction is affine.
} else if (!isAffineExpr(&Context.CurRegion, AccessFunction, *SE,
@ -443,9 +452,6 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
AccessFunction, &Inst, BaseValue);
const SCEV *ElementSize = SE->getElementSize(&Inst);
Context.ElementSize[BasePointer] = ElementSize;
// Collect all non affine memory accesses, and check whether they are linear
// at the end of scop detection. That way we can delinearize all the memory
// accesses to the same array in a unique step.

View File

@ -290,6 +290,24 @@ bool ReportVariantBasePtr::classof(const RejectReason *RR) {
return RR->getKind() == rrkVariantBasePtr;
}
//===----------------------------------------------------------------------===//
// ReportDifferentArrayElementSize
std::string ReportDifferentArrayElementSize::getMessage() const {
return "Access to one array through data types of different size";
}
bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) {
return RR->getKind() == rrkDifferentElementSize;
}
std::string ReportDifferentArrayElementSize::getEndUserMessage() const {
llvm::StringRef BaseName = BaseValue->getName();
std::string Name = (BaseName.size() > 0) ? BaseName : "UNKNOWN";
return "The array \"" + Name + "\" is accessed through elements that differ "
"in size";
}
//===----------------------------------------------------------------------===//
// ReportNonAffineAccess.

View File

@ -0,0 +1,67 @@
; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
; 1 void differenttypes(char *A)
; 2 {
; 3 for (long i = 0; i < 1024; ++i)
; 4 ((float*)A)[i] = ((double*)A)[i];
; 5 }
; CHECK: remark: /tmp/test.c:3:20: The following errors keep this region from being a Scop.
; CHECK-NEXT: remark: /tmp/test.c:4:14: The array "A" is accessed through elements that differ in size
; CHECK-NEXT: remark: /tmp/test.c:4:32: Invalid Scop candidate ends here.
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @differenttypes(i8* nocapture %A) {
entry:
br label %for.body, !dbg !10
for.body: ; preds = %for.body, %entry
%i.05 = phi i64 [ 0, %entry ], [ %tmp11, %for.body ]
%tmp = shl i64 %i.05, 3, !dbg !15
%uglygep = getelementptr i8* %A, i64 %tmp
%arrayidx = bitcast i8* %uglygep to double*, !dbg !16
%tmp9 = shl i64 %i.05, 2, !dbg !15
%uglygep7 = getelementptr i8* %A, i64 %tmp9
%arrayidx1 = bitcast i8* %uglygep7 to float*, !dbg !17
%tmp10 = load double* %arrayidx, align 8, !dbg !16, !tbaa !18
%conv = fptrunc double %tmp10 to float, !dbg !16
store float %conv, float* %arrayidx1, align 4, !dbg !17, !tbaa !22
%tmp11 = add nsw i64 %i.05, 1, !dbg !24
%exitcond = icmp eq i64 %tmp11, 1024, !dbg !10
br i1 %exitcond, label %for.end, label %for.body, !dbg !10
for.end: ; preds = %for.body
ret void, !dbg !25
}
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!7, !8}
!llvm.ident = !{!9}
!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.6.0 ", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c] [DW_LANG_C99]
!1 = metadata !{metadata !"/tmp/test.c", metadata !"/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics"}
!2 = metadata !{}
!3 = metadata !{metadata !4}
!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"differenttypes", metadata !"differenttypes", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i8*)* @differenttypes, null, null, metadata !2, i32 2} ; [ DW_TAG_subprogram ] [line 1] [def] [scope 2] [differenttypes]
!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
!8 = metadata !{i32 2, metadata !"Debug Info Version", i32 1}
!9 = metadata !{metadata !"clang version 3.6.0 "}
!10 = metadata !{i32 3, i32 20, metadata !11, null}
!11 = metadata !{i32 786443, metadata !1, metadata !12, i32 2} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
!12 = metadata !{i32 786443, metadata !1, metadata !13, i32 1} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
!13 = metadata !{i32 786443, metadata !1, metadata !14, i32 3, i32 3, i32 1} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
!14 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 3, i32 0} ; [ DW_TAG_lexical_block ] [/home/grosser/Projects/polly/git/tools/polly/test/ScopDetectionDiagnostics//tmp/test.c]
!15 = metadata !{i32 4, i32 32, metadata !13, null}
!16 = metadata !{i32 4, i32 22, metadata !13, null}
!17 = metadata !{i32 4, i32 14, metadata !13, null}
!18 = metadata !{metadata !19, metadata !19, i64 0}
!19 = metadata !{metadata !"double", metadata !20, i64 0}
!20 = metadata !{metadata !"omnipotent char", metadata !21, i64 0}
!21 = metadata !{metadata !"Simple C/C++ TBAA"}
!22 = metadata !{metadata !23, metadata !23, i64 0}
!23 = metadata !{metadata !"float", metadata !20, i64 0}
!24 = metadata !{i32 3, i32 30, metadata !13, null}
!25 = metadata !{i32 5, i32 1, metadata !4, null}