diff options
| author | Tobias Grosser <tobias@grosser.es> | 2014-09-13 14:47:40 +0000 |
|---|---|---|
| committer | Tobias Grosser <tobias@grosser.es> | 2014-09-13 14:47:40 +0000 |
| commit | bcd4efffa7879f221c2dc80462f9161412b9733c (patch) | |
| tree | 643ff5a9500668489f9505ff59ec90fa40622dd8 | |
| parent | 0bd147da174309fe295c592ef36c6229dc99f727 (diff) | |
| download | bcm5719-llvm-bcd4efffa7879f221c2dc80462f9161412b9733c.tar.gz bcm5719-llvm-bcd4efffa7879f221c2dc80462f9161412b9733c.zip | |
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
| -rw-r--r-- | polly/include/polly/ScopDetectionDiagnostic.h | 25 | ||||
| -rw-r--r-- | polly/lib/Analysis/ScopDetection.cpp | 12 | ||||
| -rw-r--r-- | polly/lib/Analysis/ScopDetectionDiagnostic.cpp | 18 | ||||
| -rw-r--r-- | polly/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll | 67 |
4 files changed, 119 insertions, 3 deletions
diff --git a/polly/include/polly/ScopDetectionDiagnostic.h b/polly/include/polly/ScopDetectionDiagnostic.h index b2dd457ce89..db91d2a3712 100644 --- a/polly/include/polly/ScopDetectionDiagnostic.h +++ b/polly/include/polly/ScopDetectionDiagnostic.h @@ -86,6 +86,7 @@ enum RejectReasonKind { rrkUndefBasePtr, rrkVariantBasePtr, rrkNonAffineAccess, + rrkDifferentElementSize, rrkLastAffFunc, // IndVar @@ -515,6 +516,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. /// // ReportIndVar reject reasons are generated when the ScopDetection finds diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp index 5865f2a90c3..ea1915d6235 100644 --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -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. diff --git a/polly/lib/Analysis/ScopDetectionDiagnostic.cpp b/polly/lib/Analysis/ScopDetectionDiagnostic.cpp index 8277329bb6d..c4c0107289a 100644 --- a/polly/lib/Analysis/ScopDetectionDiagnostic.cpp +++ b/polly/lib/Analysis/ScopDetectionDiagnostic.cpp @@ -291,6 +291,24 @@ bool ReportVariantBasePtr::classof(const RejectReason *RR) { } //===----------------------------------------------------------------------===// +// 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. std::string ReportNonAffineAccess::getMessage() const { diff --git a/polly/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll b/polly/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll new file mode 100644 index 00000000000..ff7b88e606b --- /dev/null +++ b/polly/test/ScopDetectionDiagnostics/ReportDifferentElementSize.ll @@ -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} |

