From 55306bdea5d2d53be39f3ac59fadf5220ee6b5d0 Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Fri, 21 Dec 2012 00:07:35 +0000 Subject: [PATCH] Fix a bug in the code that checks if we can vectorize loops while using dynamic memory bound checks. Before the fix we were able to vectorize this loop from the Livermore Loops benchmark: for ( k=1 ; k(*I); - assert(ST && "Bad StoreInst"); + StoreInst *ST = cast(*I); Value* Ptr = ST->getPointerOperand(); if (isUniform(Ptr)) { @@ -1609,8 +1608,7 @@ bool LoopVectorizationLegality::canVectorizeMemory() { } for (I = Loads.begin(), IE = Loads.end(); I != IE; ++I) { - LoadInst *LD = dyn_cast(*I); - assert(LD && "Bad LoadInst"); + LoadInst *LD = cast(*I); Value* Ptr = LD->getPointerOperand(); // If we did *not* see this pointer before, insert it to the // read list. If we *did* see it before, then it is already in @@ -1633,13 +1631,13 @@ bool LoopVectorizationLegality::canVectorizeMemory() { // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. - bool RT = true; + bool CanDoRT = true; for (I = ReadWrites.begin(), IE = ReadWrites.end(); I != IE; ++I) if (hasComputableBounds(*I)) { PtrRtCheck.insert(SE, TheLoop, *I); DEBUG(dbgs() << "LV: Found a runtime check ptr:" << **I <<"\n"); } else { - RT = false; + CanDoRT = false; break; } for (I = Reads.begin(), IE = Reads.end(); I != IE; ++I) @@ -1647,23 +1645,23 @@ bool LoopVectorizationLegality::canVectorizeMemory() { PtrRtCheck.insert(SE, TheLoop, *I); DEBUG(dbgs() << "LV: Found a runtime check ptr:" << **I <<"\n"); } else { - RT = false; + CanDoRT = false; break; } // Check that we did not collect too many pointers or found a // unsizeable pointer. - if (!RT || PtrRtCheck.Pointers.size() > RuntimeMemoryCheckThreshold) { + if (!CanDoRT || PtrRtCheck.Pointers.size() > RuntimeMemoryCheckThreshold) { PtrRtCheck.reset(); - RT = false; + CanDoRT = false; } - PtrRtCheck.Need = RT; - - if (RT) { + if (CanDoRT) { DEBUG(dbgs() << "LV: We can perform a memory runtime check if needed.\n"); } + bool NeedRTCheck = false; + // Now that the pointers are in two lists (Reads and ReadWrites), we // can check that there are no conflicts between each of the writes and // between the writes to the reads. @@ -1678,12 +1676,12 @@ bool LoopVectorizationLegality::canVectorizeMemory() { it != e; ++it) { if (!isIdentifiedObject(*it)) { DEBUG(dbgs() << "LV: Found an unidentified write ptr:"<< **it <<"\n"); - return RT; + NeedRTCheck = true; } if (!WriteObjects.insert(*it)) { DEBUG(dbgs() << "LV: Found a possible write-write reorder:" << **it <<"\n"); - return RT; + return false; } } TempObjects.clear(); @@ -1696,20 +1694,27 @@ bool LoopVectorizationLegality::canVectorizeMemory() { it != e; ++it) { if (!isIdentifiedObject(*it)) { DEBUG(dbgs() << "LV: Found an unidentified read ptr:"<< **it <<"\n"); - return RT; + NeedRTCheck = true; } if (WriteObjects.count(*it)) { DEBUG(dbgs() << "LV: Found a possible read/write reorder:" << **it <<"\n"); - return RT; + return false; } } TempObjects.clear(); } - // It is safe to vectorize and we don't need any runtime checks. - DEBUG(dbgs() << "LV: We don't need a runtime memory check.\n"); - PtrRtCheck.reset(); + PtrRtCheck.Need = NeedRTCheck; + if (NeedRTCheck && !CanDoRT) { + DEBUG(dbgs() << "LV: We can't vectorize because we can't find " << + "the array bounds.\n"); + PtrRtCheck.reset(); + return false; + } + + DEBUG(dbgs() << "LV: We "<< (NeedRTCheck ? "" : "don't") << + " need a runtime memory check.\n"); return true; } diff --git a/test/Transforms/LoopVectorize/same-base-access.ll b/test/Transforms/LoopVectorize/same-base-access.ll new file mode 100644 index 00000000000..f9ef32e4922 --- /dev/null +++ b/test/Transforms/LoopVectorize/same-base-access.ll @@ -0,0 +1,110 @@ +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -dce -instcombine -licm -S -enable-if-conversion | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.9.0" + +; This is kernel11 from "LivermoreLoops". We can't vectorize it because we +; access both x[k] and x[k-1]. +; +; void kernel11(double *x, double *y, int n) { +; for ( int k=1 ; k +; CHECK: ret +define i32 @kernel11(double* %x, double* %y, i32 %n) nounwind uwtable ssp { + %1 = alloca double*, align 8 + %2 = alloca double*, align 8 + %3 = alloca i32, align 4 + %k = alloca i32, align 4 + store double* %x, double** %1, align 8 + store double* %y, double** %2, align 8 + store i32 %n, i32* %3, align 4 + store i32 1, i32* %k, align 4 + br label %4 + +;