From 1e80bef8962d84375bdcb3d9d1d43a4631870499 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 14 Dec 2013 00:27:48 +0000 Subject: [PATCH] Teach MemoryBuiltins about address spaces git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197292 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/MemoryBuiltins.h | 3 + lib/Analysis/MemoryBuiltins.cpp | 16 ++++-- test/Instrumentation/BoundsChecking/phi.ll | 55 ++++++++++++++++++- test/Instrumentation/BoundsChecking/simple.ll | 24 +++++++- 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 91224ad94ac..ec2fea838fa 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -190,6 +190,8 @@ public: return knownSize(SizeOffset) && knownOffset(SizeOffset); } + // These are "private", except they can't actually be made private. Only + // compute() should be used by external users. SizeOffsetType visitAllocaInst(AllocaInst &I); SizeOffsetType visitArgument(Argument &A); SizeOffsetType visitCallSite(CallSite CS); @@ -256,6 +258,7 @@ public: return knownSize(SizeOffset) && knownOffset(SizeOffset); } + // The individual instruction visitors should be treated as private. SizeOffsetEvalType visitAllocaInst(AllocaInst &I); SizeOffsetEvalType visitCallSite(CallSite CS); SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I); diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp index 1db0f634c94..37e2e271cee 100644 --- a/lib/Analysis/MemoryBuiltins.cpp +++ b/lib/Analysis/MemoryBuiltins.cpp @@ -399,12 +399,14 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout *DL, LLVMContext &Context, bool RoundToAlign) : DL(DL), TLI(TLI), RoundToAlign(RoundToAlign) { - IntegerType *IntTy = DL->getIntPtrType(Context); - IntTyBits = IntTy->getBitWidth(); - Zero = APInt::getNullValue(IntTyBits); + // Pointer size must be rechecked for each object visited since it could have + // a different address space. } SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { + IntTyBits = DL->getPointerTypeSizeInBits(V->getType()); + Zero = APInt::getNullValue(IntTyBits); + V = V->stripPointerCasts(); if (Instruction *I = dyn_cast(V)) { // If we have already seen this instruction, bail out. Cycles can happen in @@ -592,11 +594,15 @@ ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const DataLayout *DL, bool RoundToAlign) : DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)), RoundToAlign(RoundToAlign) { - IntTy = DL->getIntPtrType(Context); - Zero = ConstantInt::get(IntTy, 0); + // IntTy and Zero must be set for each compute() since the address space may + // be different for later objects. } SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) { + // XXX - Are vectors of pointers possible here? + IntTy = cast(DL->getIntPtrType(V->getType())); + Zero = ConstantInt::get(IntTy, 0); + SizeOffsetEvalType Result = compute_(V); if (!bothKnown(Result)) { diff --git a/test/Instrumentation/BoundsChecking/phi.ll b/test/Instrumentation/BoundsChecking/phi.ll index 86b59222707..0f9d1b0b54b 100644 --- a/test/Instrumentation/BoundsChecking/phi.ll +++ b/test/Instrumentation/BoundsChecking/phi.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -bounds-checking -S | 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 datalayout = "e-p:64:64:64-p1:16:16:16-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" @global = private unnamed_addr constant [10 x i8] c"ola\00mundo\00", align 1 @@ -50,3 +50,56 @@ while.body.i: fn.exit: ret void } + + +@global_as1 = private addrspace(1) unnamed_addr constant [10 x i8] c"ola\00mundo\00", align 1 + +define void @f1_as1(i8 addrspace(1)* nocapture %c) { +; CHECK: @f1_as1 +; no checks are possible here +; CHECK-NOT: trap +; CHECK: add i16 undef, -1 +; CHECK-NOT: trap +entry: + %0 = load i8 addrspace(1)* %c, align 1 + %tobool1 = icmp eq i8 %0, 0 + br i1 %tobool1, label %while.end, label %while.body + +while.body: + %c.addr.02 = phi i8 addrspace(1)* [ %incdec.ptr, %while.body ], [ %c, %entry ] + %incdec.ptr = getelementptr inbounds i8 addrspace(1)* %c.addr.02, i64 -1 + store i8 100, i8 addrspace(1)* %c.addr.02, align 1 + %1 = load i8 addrspace(1)* %incdec.ptr, align 1 + %tobool = icmp eq i8 %1, 0 + br i1 %tobool, label %while.end, label %while.body + +while.end: + ret void +} + + +define void @f2_as1() { +; CHECK: @f2_as1 +while.body.i.preheader: + %addr = getelementptr inbounds [10 x i8] addrspace(1)* @global_as1, i16 0, i16 9 + br label %while.body.i + +while.body.i: +; CHECK: phi +; CHECK-NEXT: phi +; CHECK-NOT: phi + %c.addr.02.i = phi i8 addrspace(1)* [ %incdec.ptr.i, %while.body.i ], [ %addr, %while.body.i.preheader ] + %incdec.ptr.i = getelementptr inbounds i8 addrspace(1)* %c.addr.02.i, i16 -1 +; CHECK: sub i16 10, %0 +; CHECK-NEXT: icmp ult i16 10, %0 +; CHECK-NEXT: icmp ult i16 {{.*}}, 1 +; CHECK-NEXT: or i1 +; CHECK-NEXT: br {{.*}}, label %trap + store i8 100, i8 addrspace(1)* %c.addr.02.i, align 1 + %0 = load i8 addrspace(1)* %incdec.ptr.i, align 1 + %tobool.i = icmp eq i8 %0, 0 + br i1 %tobool.i, label %fn.exit, label %while.body.i + +fn.exit: + ret void +} diff --git a/test/Instrumentation/BoundsChecking/simple.ll b/test/Instrumentation/BoundsChecking/simple.ll index 72b58f4b0a3..ddacf6d412b 100644 --- a/test/Instrumentation/BoundsChecking/simple.ll +++ b/test/Instrumentation/BoundsChecking/simple.ll @@ -1,8 +1,11 @@ ; RUN: opt < %s -bounds-checking -S | 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 datalayout = "e-p:64:64:64-p1:16:16:16-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" @.str = private constant [8 x i8] c"abcdefg\00" ; <[8 x i8]*> +@.str_as1 = private addrspace(1) constant [8 x i8] c"abcdefg\00" ; <[8 x i8] addrspace(1)*> + + declare noalias i8* @malloc(i64) nounwind declare noalias i8* @calloc(i64, i64) nounwind declare noalias i8* @realloc(i8* nocapture, i64) nounwind @@ -60,6 +63,16 @@ define void @f5(i64 %x) nounwind { ret void } +define void @f5_as1(i64 %x) nounwind { +; CHECK: @f5_as1 + %idx = getelementptr inbounds [8 x i8] addrspace(1)* @.str_as1, i64 0, i64 %x + ; CHECK: sub i16 + ; CHECK icmp ult i16 +; CHECK: trap + %1 = load i8 addrspace(1)* %idx, align 4 + ret void +} + ; CHECK: @f6 define void @f6(i64 %x) nounwind { %1 = alloca i128 @@ -117,6 +130,15 @@ define void @f11(i128* byval %x) nounwind { ret void } +; CHECK: @f11_as1 +define void @f11_as1(i128 addrspace(1)* byval %x) nounwind { + %1 = bitcast i128 addrspace(1)* %x to i8 addrspace(1)* + %2 = getelementptr inbounds i8 addrspace(1)* %1, i16 16 +; CHECK: br label + %3 = load i8 addrspace(1)* %2, align 4 + ret void +} + ; CHECK: @f12 define i64 @f12(i64 %x, i64 %y) nounwind { %1 = tail call i8* @calloc(i64 1, i64 %x) -- 2.34.1