From 43a38e2759e81beaf41224a58c04b9db603e62aa Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 2 May 2024 19:13:14 -0700 Subject: [PATCH] [BoundsChecking] Handle vscale allocas (#90926) --- llvm/lib/Analysis/MemoryBuiltins.cpp | 8 +-- .../Instrumentation/BoundsChecking/simple.ll | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 46a7a921d86d3d..8ca15434833d9d 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -1138,8 +1138,8 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { if (!I.getAllocatedType()->isSized()) return ObjectSizeOffsetEvaluator::unknown(); - // must be a VLA - assert(I.isArrayAllocation()); + // must be a VLA or vscale. + assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy()); // If needed, adjust the alloca's operand size to match the pointer indexing // size. Subsequent math operations expect the types to match. @@ -1149,8 +1149,8 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { assert(ArraySize->getType() == Zero->getType() && "Expected zero constant to have pointer index type"); - Value *Size = ConstantInt::get(ArraySize->getType(), - DL.getTypeAllocSize(I.getAllocatedType())); + Value *Size = Builder.CreateTypeSize( + ArraySize->getType(), DL.getTypeAllocSize(I.getAllocatedType())); Size = Builder.CreateMul(Size, ArraySize); return SizeOffsetValue(Size, Zero); } diff --git a/llvm/test/Instrumentation/BoundsChecking/simple.ll b/llvm/test/Instrumentation/BoundsChecking/simple.ll index 60d124f0b89735..914cafdc57f9d3 100644 --- a/llvm/test/Instrumentation/BoundsChecking/simple.ll +++ b/llvm/test/Instrumentation/BoundsChecking/simple.ll @@ -488,3 +488,69 @@ define @load_scalable_vector(i64 %y) nounwind { %3 = load , ptr %2, align 8 ret %3 } + +define void @scalable_alloca(i64 %y) nounwind { +; CHECK-LABEL: @scalable_alloca( +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 8 +; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 5 +; CHECK-NEXT: [[TMP4:%.*]] = alloca , i32 5, align 8 +; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 8 +; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], [[TMP6]] +; CHECK-NEXT: [[TMP7:%.*]] = add i64 0, [[DOTIDX]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds , ptr [[TMP4]], i64 [[Y]] +; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 8 +; CHECK-NEXT: [[TMP11:%.*]] = sub i64 [[TMP3]], [[TMP7]] +; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP3]], [[TMP7]] +; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i64 [[TMP11]], [[TMP10]] +; CHECK-NEXT: [[TMP14:%.*]] = or i1 [[TMP12]], [[TMP13]] +; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i64 [[TMP7]], 0 +; CHECK-NEXT: [[TMP16:%.*]] = or i1 [[TMP15]], [[TMP14]] +; CHECK-NEXT: br i1 [[TMP16]], label [[TRAP:%.*]], label [[TMP17:%.*]] +; CHECK: 17: +; CHECK-NEXT: [[TMP18:%.*]] = load , ptr [[TMP8]], align 4 +; CHECK-NEXT: ret void +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]] +; CHECK-NEXT: unreachable +; + %1 = alloca , i32 5 + %2 = getelementptr inbounds , ptr %1, i64 %y + %3 = load , ptr %2, align 4 + ret void +} + +define void @scalable_alloca2(i64 %y) nounwind { +; CHECK-LABEL: @scalable_alloca2( +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 32 +; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = alloca , align 32 +; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 32 +; CHECK-NEXT: [[DOTIDX:%.*]] = mul i64 [[Y:%.*]], [[TMP6]] +; CHECK-NEXT: [[TMP7:%.*]] = add i64 0, [[DOTIDX]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds , ptr [[TMP4]], i64 [[Y]] +; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 32 +; CHECK-NEXT: [[TMP11:%.*]] = sub i64 [[TMP3]], [[TMP7]] +; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP3]], [[TMP7]] +; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i64 [[TMP11]], [[TMP10]] +; CHECK-NEXT: [[TMP14:%.*]] = or i1 [[TMP12]], [[TMP13]] +; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i64 [[TMP7]], 0 +; CHECK-NEXT: [[TMP16:%.*]] = or i1 [[TMP15]], [[TMP14]] +; CHECK-NEXT: br i1 [[TMP16]], label [[TRAP:%.*]], label [[TMP17:%.*]] +; CHECK: 17: +; CHECK-NEXT: [[TMP18:%.*]] = load , ptr [[TMP8]], align 4 +; CHECK-NEXT: ret void +; CHECK: trap: +; CHECK-NEXT: call void @llvm.trap() #[[ATTR6]] +; CHECK-NEXT: unreachable +; + %1 = alloca + %2 = getelementptr inbounds , ptr %1, i64 %y + %3 = load , ptr %2, align 4 + ret void +}