mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 01:06:06 +00:00
Add a 'dynamic' parameter to the objectsize intrinsic
This is meant to be used with clang's __builtin_dynamic_object_size. When 'true' is passed to this parameter, the intrinsic has the potential to be folded into instructions that will be evaluated at run time. When 'false', the objectsize intrinsic behaviour is unchanged. rdar://32212419 Differential revision: https://reviews.llvm.org/D56761 llvm-svn: 352664
This commit is contained in:
parent
7e880b0262
commit
600e9deacf
@ -549,7 +549,8 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
|
||||
Value *Min = Builder.getInt1((Type & 2) != 0);
|
||||
// For GCC compatibility, __builtin_object_size treat NULL as unknown size.
|
||||
Value *NullIsUnknown = Builder.getTrue();
|
||||
return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown});
|
||||
Value *Dynamic = Builder.getFalse();
|
||||
return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown, Dynamic});
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -727,9 +727,10 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
|
||||
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
|
||||
llvm::Value *Min = Builder.getFalse();
|
||||
llvm::Value *NullIsUnknown = Builder.getFalse();
|
||||
llvm::Value *Dynamic = Builder.getFalse();
|
||||
llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy);
|
||||
llvm::Value *LargeEnough = Builder.CreateICmpUGE(
|
||||
Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown}), Size);
|
||||
Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown, Dynamic}), Size);
|
||||
Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ void test7() {
|
||||
void test8() {
|
||||
// Non-const pointers aren't currently supported.
|
||||
void *buf = my_calloc(100, 5);
|
||||
// CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(buf, 0);
|
||||
// CHECK: @llvm.objectsize
|
||||
gi = __builtin_object_size(buf, 1);
|
||||
|
@ -35,7 +35,7 @@ void foo() {
|
||||
union { int i; } u;
|
||||
|
||||
// CHECK-COMMON: %[[I8PTR:.*]] = bitcast i32* %[[PTR:.*]] to i8*
|
||||
// CHECK-COMMON-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false, i1 false)
|
||||
// CHECK-COMMON-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false, i1 false, i1 false)
|
||||
// CHECK-COMMON-NEXT: %[[OK:.*]] = icmp uge i64 %[[SIZE]], 4
|
||||
|
||||
// CHECK-UBSAN: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize
|
||||
|
@ -40,7 +40,7 @@ void test4() {
|
||||
// CHECK-LABEL: define void @test5
|
||||
void test5() {
|
||||
// CHECK: = load i8*, i8** @gp
|
||||
// CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false)
|
||||
strcpy(gp, "Hi there");
|
||||
}
|
||||
|
||||
@ -254,31 +254,31 @@ struct Test23Ty { int a; int t[10]; };
|
||||
|
||||
// CHECK-LABEL: @test23
|
||||
void test23(struct Test23Ty *p) {
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(p, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(p, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(p, 2);
|
||||
// Note: this is currently fixed at 0 because LLVM doesn't have sufficient
|
||||
// data to correctly handle type=3
|
||||
// CHECK: store i32 0
|
||||
gi = __builtin_object_size(p, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&p->a, 0);
|
||||
// CHECK: store i32 4
|
||||
gi = __builtin_object_size(&p->a, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(&p->a, 2);
|
||||
// CHECK: store i32 4
|
||||
gi = __builtin_object_size(&p->a, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&p->t[5], 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&p->t[5], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(&p->t[5], 2);
|
||||
// CHECK: store i32 20
|
||||
gi = __builtin_object_size(&p->t[5], 3);
|
||||
@ -287,11 +287,11 @@ void test23(struct Test23Ty *p) {
|
||||
// PR24493 -- ICE if __builtin_object_size called with NULL and (Type & 1) != 0
|
||||
// CHECK-LABEL: @test24
|
||||
void test24() {
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0, 2);
|
||||
// Note: Currently fixed at zero because LLVM can't handle type=3 correctly.
|
||||
// Hopefully will be lowered properly in the future.
|
||||
@ -301,22 +301,22 @@ void test24() {
|
||||
|
||||
// CHECK-LABEL: @test25
|
||||
void test25() {
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0x1000, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0x1000, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0x1000, 2);
|
||||
// Note: Currently fixed at zero because LLVM can't handle type=3 correctly.
|
||||
// Hopefully will be lowered properly in the future.
|
||||
// CHECK: store i32 0
|
||||
gi = __builtin_object_size((void*)0x1000, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0 + 0x1000, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0 + 0x1000, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size((void*)0 + 0x1000, 2);
|
||||
// Note: Currently fixed at zero because LLVM can't handle type=3 correctly.
|
||||
// Hopefully will be lowered properly in the future.
|
||||
@ -342,22 +342,22 @@ struct Test27IncompleteTy;
|
||||
|
||||
// CHECK-LABEL: @test27
|
||||
void test27(struct Test27IncompleteTy *t) {
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(t, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(t, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(t, 2);
|
||||
// Note: this is currently fixed at 0 because LLVM doesn't have sufficient
|
||||
// data to correctly handle type=3
|
||||
// CHECK: store i32 0
|
||||
gi = __builtin_object_size(t, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&test27, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&test27, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(&test27, 2);
|
||||
// Note: this is currently fixed at 0 because LLVM doesn't have sufficient
|
||||
// data to correctly handle type=3
|
||||
@ -415,38 +415,38 @@ struct StaticStruct {
|
||||
// CHECK-LABEL: @test29
|
||||
void test29(struct DynStructVar *dv, struct DynStruct0 *d0,
|
||||
struct DynStruct1 *d1, struct StaticStruct *ss) {
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(dv->snd, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(dv->snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(dv->snd, 2);
|
||||
// CHECK: store i32 0
|
||||
gi = __builtin_object_size(dv->snd, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(d0->snd, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(d0->snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(d0->snd, 2);
|
||||
// CHECK: store i32 0
|
||||
gi = __builtin_object_size(d0->snd, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(d1->snd, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(d1->snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(d1->snd, 2);
|
||||
// CHECK: store i32 1
|
||||
gi = __builtin_object_size(d1->snd, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(ss->snd, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(ss->snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(ss->snd, 2);
|
||||
// CHECK: store i32 2
|
||||
gi = __builtin_object_size(ss->snd, 3);
|
||||
@ -456,39 +456,39 @@ void test29(struct DynStructVar *dv, struct DynStruct0 *d0,
|
||||
void test30() {
|
||||
struct { struct DynStruct1 fst, snd; } *nested;
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(nested->fst.snd, 0);
|
||||
// CHECK: store i32 1
|
||||
gi = __builtin_object_size(nested->fst.snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(nested->fst.snd, 2);
|
||||
// CHECK: store i32 1
|
||||
gi = __builtin_object_size(nested->fst.snd, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(nested->snd.snd, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(nested->snd.snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(nested->snd.snd, 2);
|
||||
// CHECK: store i32 1
|
||||
gi = __builtin_object_size(nested->snd.snd, 3);
|
||||
|
||||
union { struct DynStruct1 d1; char c[1]; } *u;
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(u->c, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(u->c, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(u->c, 2);
|
||||
// CHECK: store i32 1
|
||||
gi = __builtin_object_size(u->c, 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(u->d1.snd, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(u->d1.snd, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(u->d1.snd, 2);
|
||||
// CHECK: store i32 1
|
||||
gi = __builtin_object_size(u->d1.snd, 3);
|
||||
@ -502,19 +502,19 @@ void test31() {
|
||||
struct DynStruct1 *ds1;
|
||||
struct StaticStruct *ss;
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(ds1[9].snd, 1);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&ss[9].snd[0], 1);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&ds1[9].snd[0], 1);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&ds0[9].snd[0], 1);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(&dsv[9].snd[0], 1);
|
||||
}
|
||||
|
||||
@ -527,11 +527,11 @@ void PR30346() {
|
||||
};
|
||||
|
||||
struct sockaddr *sa;
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(sa->sa_data, 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1
|
||||
gi = __builtin_object_size(sa->sa_data, 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1
|
||||
gi = __builtin_object_size(sa->sa_data, 2);
|
||||
// CHECK: store i32 14
|
||||
gi = __builtin_object_size(sa->sa_data, 3);
|
||||
|
@ -35,29 +35,29 @@ void test2() {
|
||||
struct B : A {};
|
||||
struct C { int i; B bs[1]; } *c;
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 0);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0], 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size((A*)&c->bs[0], 0);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size((A*)&c->bs[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size((A*)&c->bs[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size((A*)&c->bs[0], 3);
|
||||
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 0);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 1);
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true)
|
||||
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true, i1 true, i1 false)
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 2);
|
||||
// CHECK: store i32 16
|
||||
gi = __builtin_object_size(&c->bs[0].buf[0], 3);
|
||||
|
@ -15575,40 +15575,40 @@ Syntax:
|
||||
|
||||
::
|
||||
|
||||
declare i32 @llvm.objectsize.i32(i8* <object>, i1 <min>, i1 <nullunknown>)
|
||||
declare i64 @llvm.objectsize.i64(i8* <object>, i1 <min>, i1 <nullunknown>)
|
||||
declare i32 @llvm.objectsize.i32(i8* <object>, i1 <min>, i1 <nullunknown>, i1 <dynamic>)
|
||||
declare i64 @llvm.objectsize.i64(i8* <object>, i1 <min>, i1 <nullunknown>, i1 <dynamic>)
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
||||
The ``llvm.objectsize`` intrinsic is designed to provide information to
|
||||
the optimizers to determine at compile time whether a) an operation
|
||||
(like memcpy) will overflow a buffer that corresponds to an object, or
|
||||
b) that a runtime check for overflow isn't necessary. An object in this
|
||||
context means an allocation of a specific class, structure, array, or
|
||||
other object.
|
||||
The ``llvm.objectsize`` intrinsic is designed to provide information to the
|
||||
optimizer to determine whether a) an operation (like memcpy) will overflow a
|
||||
buffer that corresponds to an object, or b) that a runtime check for overflow
|
||||
isn't necessary. An object in this context means an allocation of a specific
|
||||
class, structure, array, or other object.
|
||||
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The ``llvm.objectsize`` intrinsic takes three arguments. The first argument is
|
||||
a pointer to or into the ``object``. The second argument determines whether
|
||||
``llvm.objectsize`` returns 0 (if true) or -1 (if false) when the object size
|
||||
is unknown. The third argument controls how ``llvm.objectsize`` acts when
|
||||
``null`` in address space 0 is used as its pointer argument. If it's ``false``,
|
||||
The ``llvm.objectsize`` intrinsic takes four arguments. The first argument is a
|
||||
pointer to or into the ``object``. The second argument determines whether
|
||||
``llvm.objectsize`` returns 0 (if true) or -1 (if false) when the object size is
|
||||
unknown. The third argument controls how ``llvm.objectsize`` acts when ``null``
|
||||
in address space 0 is used as its pointer argument. If it's ``false``,
|
||||
``llvm.objectsize`` reports 0 bytes available when given ``null``. Otherwise, if
|
||||
the ``null`` is in a non-zero address space or if ``true`` is given for the
|
||||
third argument of ``llvm.objectsize``, we assume its size is unknown.
|
||||
third argument of ``llvm.objectsize``, we assume its size is unknown. The fourth
|
||||
argument to ``llvm.objectsize`` determines if the value should be evaluated at
|
||||
runtime.
|
||||
|
||||
The second and third arguments only accept constants.
|
||||
The second, third, and fourth arguments only accept constants.
|
||||
|
||||
Semantics:
|
||||
""""""""""
|
||||
|
||||
The ``llvm.objectsize`` intrinsic is lowered to a constant representing
|
||||
the size of the object concerned. If the size cannot be determined at
|
||||
compile time, ``llvm.objectsize`` returns ``i32/i64 -1 or 0`` (depending
|
||||
on the ``min`` argument).
|
||||
The ``llvm.objectsize`` intrinsic is lowered to a value representing the size of
|
||||
the object concerned. If the size cannot be determined, ``llvm.objectsize``
|
||||
returns ``i32/i64 -1 or 0`` (depending on the ``min`` argument).
|
||||
|
||||
'``llvm.expect``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -177,14 +177,13 @@ bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
|
||||
|
||||
/// Try to turn a call to \@llvm.objectsize into an integer value of the given
|
||||
/// Type. Returns null on failure.
|
||||
/// If MustSucceed is true, this function will not return null, and may return
|
||||
/// conservative values governed by the second argument of the call to
|
||||
/// objectsize.
|
||||
ConstantInt *lowerObjectSizeCall(IntrinsicInst *ObjectSize,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI,
|
||||
bool MustSucceed);
|
||||
/// Type. Returns null on failure. If MustSucceed is true, this function will
|
||||
/// not return null, and may return conservative values governed by the second
|
||||
/// argument of the call to objectsize.
|
||||
Value *lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI, bool MustSucceed);
|
||||
|
||||
|
||||
|
||||
using SizeOffsetType = std::pair<APInt, APInt>;
|
||||
|
||||
@ -264,17 +263,17 @@ class ObjectSizeOffsetEvaluator
|
||||
Value *Zero;
|
||||
CacheMapTy CacheMap;
|
||||
PtrSetTy SeenVals;
|
||||
bool RoundToAlign;
|
||||
|
||||
SizeOffsetEvalType unknown() {
|
||||
return std::make_pair(nullptr, nullptr);
|
||||
}
|
||||
ObjectSizeOpts EvalOpts;
|
||||
|
||||
SizeOffsetEvalType compute_(Value *V);
|
||||
|
||||
public:
|
||||
static SizeOffsetEvalType unknown() {
|
||||
return std::make_pair(nullptr, nullptr);
|
||||
}
|
||||
|
||||
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
|
||||
LLVMContext &Context, bool RoundToAlign = false);
|
||||
LLVMContext &Context, ObjectSizeOpts EvalOpts = {});
|
||||
|
||||
SizeOffsetEvalType compute(Value *V);
|
||||
|
||||
|
@ -558,7 +558,8 @@ def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>;
|
||||
|
||||
// Internal interface for object size checking
|
||||
def int_objectsize : Intrinsic<[llvm_anyint_ty],
|
||||
[llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty],
|
||||
[llvm_anyptr_ty, llvm_i1_ty,
|
||||
llvm_i1_ty, llvm_i1_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>,
|
||||
GCCBuiltin<"__builtin_object_size">;
|
||||
|
||||
|
@ -441,10 +441,10 @@ bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
|
||||
return true;
|
||||
}
|
||||
|
||||
ConstantInt *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI,
|
||||
bool MustSucceed) {
|
||||
Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI,
|
||||
bool MustSucceed) {
|
||||
assert(ObjectSize->getIntrinsicID() == Intrinsic::objectsize &&
|
||||
"ObjectSize must be a call to llvm.objectsize!");
|
||||
|
||||
@ -461,13 +461,35 @@ ConstantInt *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
|
||||
EvalOptions.NullIsUnknownSize =
|
||||
cast<ConstantInt>(ObjectSize->getArgOperand(2))->isOne();
|
||||
|
||||
// FIXME: Does it make sense to just return a failure value if the size won't
|
||||
// fit in the output and `!MustSucceed`?
|
||||
uint64_t Size;
|
||||
auto *ResultType = cast<IntegerType>(ObjectSize->getType());
|
||||
if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) &&
|
||||
isUIntN(ResultType->getBitWidth(), Size))
|
||||
return ConstantInt::get(ResultType, Size);
|
||||
bool StaticOnly = cast<ConstantInt>(ObjectSize->getArgOperand(3))->isZero();
|
||||
if (StaticOnly) {
|
||||
// FIXME: Does it make sense to just return a failure value if the size won't
|
||||
// fit in the output and `!MustSucceed`?
|
||||
uint64_t Size;
|
||||
if (getObjectSize(ObjectSize->getArgOperand(0), Size, DL, TLI, EvalOptions) &&
|
||||
isUIntN(ResultType->getBitWidth(), Size))
|
||||
return ConstantInt::get(ResultType, Size);
|
||||
} else {
|
||||
LLVMContext &Ctx = ObjectSize->getFunction()->getContext();
|
||||
ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions);
|
||||
SizeOffsetEvalType SizeOffsetPair =
|
||||
Eval.compute(ObjectSize->getArgOperand(0));
|
||||
|
||||
if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) {
|
||||
IRBuilder<TargetFolder> Builder(Ctx, TargetFolder(DL));
|
||||
Builder.SetInsertPoint(ObjectSize);
|
||||
|
||||
// If we've outside the end of the object, then we can always access
|
||||
// exactly 0 bytes.
|
||||
Value *ResultSize =
|
||||
Builder.CreateSub(SizeOffsetPair.first, SizeOffsetPair.second);
|
||||
Value *UseZero =
|
||||
Builder.CreateICmpULT(SizeOffsetPair.first, SizeOffsetPair.second);
|
||||
return Builder.CreateSelect(UseZero, ConstantInt::get(ResultType, 0),
|
||||
ResultSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (!MustSucceed)
|
||||
return nullptr;
|
||||
@ -742,9 +764,9 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
|
||||
|
||||
ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(
|
||||
const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
|
||||
bool RoundToAlign)
|
||||
ObjectSizeOpts EvalOpts)
|
||||
: DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)),
|
||||
RoundToAlign(RoundToAlign) {
|
||||
EvalOpts(EvalOpts) {
|
||||
// IntTy and Zero must be set for each compute() since the address space may
|
||||
// be different for later objects.
|
||||
}
|
||||
@ -773,10 +795,7 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
|
||||
}
|
||||
|
||||
SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
|
||||
ObjectSizeOpts ObjSizeOptions;
|
||||
ObjSizeOptions.RoundToAlign = RoundToAlign;
|
||||
|
||||
ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, ObjSizeOptions);
|
||||
ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, EvalOpts);
|
||||
SizeOffsetType Const = Visitor.compute(V);
|
||||
if (Visitor.bothKnown(Const))
|
||||
return std::make_pair(ConstantInt::get(Context, Const.first),
|
||||
|
@ -1705,7 +1705,7 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool &ModifiedDT) {
|
||||
default: break;
|
||||
case Intrinsic::objectsize: {
|
||||
// Lower all uses of llvm.objectsize.*
|
||||
ConstantInt *RetVal =
|
||||
Value *RetVal =
|
||||
lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true);
|
||||
|
||||
resetIteratorIfInvalidatedWhileCalling(BB, [&]() {
|
||||
|
@ -3459,8 +3459,10 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
|
||||
Value *NullIsUnknownSize = CI->getNumArgOperands() == 2
|
||||
? Builder.getFalse()
|
||||
: CI->getArgOperand(2);
|
||||
Value *Dynamic =
|
||||
CI->getNumArgOperands() < 3 ? Builder.getFalse() : CI->getArgOperand(3);
|
||||
NewCall = Builder.CreateCall(
|
||||
NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize});
|
||||
NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize, Dynamic});
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -918,7 +918,8 @@ bool AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I, bool SufficientLDS) {
|
||||
);
|
||||
|
||||
CallInst *NewCall = Builder.CreateCall(
|
||||
ObjectSize, {Src, Intr->getOperand(1), Intr->getOperand(2)});
|
||||
ObjectSize,
|
||||
{Src, Intr->getOperand(1), Intr->getOperand(2), Intr->getOperand(3)});
|
||||
Intr->replaceAllUsesWith(NewCall);
|
||||
Intr->eraseFromParent();
|
||||
continue;
|
||||
|
@ -1894,9 +1894,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
||||
switch (II->getIntrinsicID()) {
|
||||
default: break;
|
||||
case Intrinsic::objectsize:
|
||||
if (ConstantInt *N =
|
||||
lowerObjectSizeCall(II, DL, &TLI, /*MustSucceed=*/false))
|
||||
return replaceInstUsesWith(CI, N);
|
||||
if (Value *V = lowerObjectSizeCall(II, DL, &TLI, /*MustSucceed=*/false))
|
||||
return replaceInstUsesWith(CI, V);
|
||||
return nullptr;
|
||||
case Intrinsic::bswap: {
|
||||
Value *IIOperand = II->getArgOperand(0);
|
||||
|
@ -2295,8 +2295,8 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
|
||||
|
||||
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
|
||||
if (II->getIntrinsicID() == Intrinsic::objectsize) {
|
||||
ConstantInt *Result = lowerObjectSizeCall(II, DL, &TLI,
|
||||
/*MustSucceed=*/true);
|
||||
Value *Result =
|
||||
lowerObjectSizeCall(II, DL, &TLI, /*MustSucceed=*/true);
|
||||
replaceInstUsesWith(*I, Result);
|
||||
eraseInstFromFunction(*I);
|
||||
Users[i] = nullptr; // Skip examining in the next loop.
|
||||
|
@ -142,8 +142,9 @@ static void insertBoundsCheck(Value *Or, BuilderTy IRB, GetTrapBBT GetTrapBB) {
|
||||
static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
|
||||
ScalarEvolution &SE) {
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
ObjectSizeOffsetEvaluator ObjSizeEval(DL, &TLI, F.getContext(),
|
||||
/*RoundToAlign=*/true);
|
||||
ObjectSizeOpts EvalOpts;
|
||||
EvalOpts.RoundToAlign = true;
|
||||
ObjectSizeOffsetEvaluator ObjSizeEval(DL, &TLI, F.getContext(), EvalOpts);
|
||||
|
||||
// check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
|
||||
// touching instructions
|
||||
|
@ -53,7 +53,7 @@ entry:
|
||||
|
||||
define i32 @test.objectsize() {
|
||||
; CHECK-LABEL: @test.objectsize(
|
||||
; CHECK: @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
; CHECK: @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
%s = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false)
|
||||
ret i32 %s
|
||||
}
|
||||
@ -61,12 +61,11 @@ define i32 @test.objectsize() {
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readonly
|
||||
define i64 @test.objectsize.2() {
|
||||
; CHECK-LABEL: @test.objectsize.2(
|
||||
; CHECK: @llvm.objectsize.i64.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
; CHECK: @llvm.objectsize.i64.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
%s = call i64 @llvm.objectsize.i64.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false)
|
||||
ret i64 %s
|
||||
}
|
||||
|
||||
|
||||
declare <2 x double> @llvm.masked.load.v2f64(<2 x double>* %ptrs, i32, <2 x i1> %mask, <2 x double> %src0)
|
||||
|
||||
define <2 x double> @tests.masked.load(<2 x double>* %ptr, <2 x i1> %mask, <2 x double> %passthru) {
|
||||
|
@ -8,7 +8,7 @@ declare void @llvm.memmove.p1i8.p0i8.i32(i8 addrspace(1)* nocapture, i8* nocaptu
|
||||
|
||||
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) #0
|
||||
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) #1
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) #1
|
||||
|
||||
; CHECK-LABEL: @promote_with_memcpy(
|
||||
; CHECK: getelementptr inbounds [64 x [17 x i32]], [64 x [17 x i32]] addrspace(3)* @promote_with_memcpy.alloca, i32 0, i32 %{{[0-9]+}}
|
||||
@ -52,11 +52,11 @@ define amdgpu_kernel void @promote_with_memset(i32 addrspace(1)* %out, i32 addrs
|
||||
|
||||
; CHECK-LABEL: @promote_with_objectsize(
|
||||
; CHECK: [[PTR:%[0-9]+]] = getelementptr inbounds [64 x [17 x i32]], [64 x [17 x i32]] addrspace(3)* @promote_with_objectsize.alloca, i32 0, i32 %{{[0-9]+}}
|
||||
; CHECK: call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %alloca.bc, i1 false, i1 false)
|
||||
; CHECK: call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %alloca.bc, i1 false, i1 false, i1 false)
|
||||
define amdgpu_kernel void @promote_with_objectsize(i32 addrspace(1)* %out) #0 {
|
||||
%alloca = alloca [17 x i32], align 4
|
||||
%alloca.bc = bitcast [17 x i32]* %alloca to i8*
|
||||
%size = call i32 @llvm.objectsize.i32.p0i8(i8* %alloca.bc, i1 false, i1 false)
|
||||
%size = call i32 @llvm.objectsize.i32.p0i8(i8* %alloca.bc, i1 false, i1 false, i1 false)
|
||||
store i32 %size, i32 addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone
|
||||
declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1) nounwind readnone
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone
|
||||
|
||||
declare i32 @subfun_1()
|
||||
declare i32 @subfun_2()
|
||||
@ -44,7 +44,7 @@ define i1 @test_objectsize(i8* %obj) nounwind {
|
||||
; CHECK-O2: %bb.0:
|
||||
; CHECK-O2: movb $1, %al
|
||||
; CHECK-O2-NEXT: retq
|
||||
%os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false)
|
||||
%os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false)
|
||||
%v = call i1 @llvm.is.constant.i64(i64 %os)
|
||||
ret i1 %v
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ bb:
|
||||
%tmp2 = getelementptr inbounds [1024 x i8], [1024 x i8]* %tmp, i64 0, i64 0
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp2, i8* %arg1, i64 1024, i1 false)
|
||||
; CHECK: call void @llvm.memcpy
|
||||
%tmp3 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 false, i1 true)
|
||||
%tmp3 = call i64 @llvm.objectsize.i64.p0i8(i8* %tmp2, i1 false, i1 true, i1 false)
|
||||
%tmp4 = call i8* @__strncpy_chk(i8* %arg2, i8* %tmp2, i64 1023, i64 %tmp3)
|
||||
; CHECK-NOT: call
|
||||
; CHECK: call i8* @strncpy(i8* %arg2, i8* nonnull %tmp2, i64 1023)
|
||||
@ -33,7 +33,7 @@ bb:
|
||||
|
||||
declare i8* @my_special_strncpy(i8* %arg1, i8* %arg2, i64 %size)
|
||||
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1)
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
|
||||
|
||||
declare i8* @__strncpy_chk(i8*, i8*, i64, i64)
|
||||
|
||||
|
@ -9,7 +9,7 @@ target triple = "x86_64-apple-darwin10.0.0"
|
||||
; rdar://8785296
|
||||
define i32 @test1(i8* %ptr) nounwind ssp noredzone align 2 {
|
||||
entry:
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false)
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false, i1 false)
|
||||
%1 = icmp ugt i64 %0, 3
|
||||
br i1 %1, label %T, label %trap
|
||||
|
||||
@ -29,7 +29,7 @@ T:
|
||||
define i64 @test_objectsize_null_flag(i8* %ptr) {
|
||||
entry:
|
||||
; CHECK: ret i64 -1
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 false, i1 true)
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 false, i1 true, i1 false)
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ entry:
|
||||
define i64 @test_objectsize_null_flag_min(i8* %ptr) {
|
||||
entry:
|
||||
; CHECK: ret i64 0
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 true, i1 true)
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* null, i1 true, i1 true, i1 false)
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ define i64 @test_objectsize_null_flag_noas0() {
|
||||
entry:
|
||||
; CHECK: ret i64 -1
|
||||
%0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false,
|
||||
i1 true)
|
||||
i1 true, i1 false)
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ define i64 @test_objectsize_null_flag_min_noas0() {
|
||||
entry:
|
||||
; CHECK: ret i64 0
|
||||
%0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true,
|
||||
i1 true)
|
||||
i1 true, i1 false)
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ define i64 @test_objectsize_null_known_flag_noas0() {
|
||||
entry:
|
||||
; CHECK: ret i64 -1
|
||||
%0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 false,
|
||||
i1 false)
|
||||
i1 false, i1 false)
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
@ -75,12 +75,12 @@ define i64 @test_objectsize_null_known_flag_min_noas0() {
|
||||
entry:
|
||||
; CHECK: ret i64 0
|
||||
%0 = tail call i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)* null, i1 true,
|
||||
i1 false)
|
||||
i1 false, i1 false)
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
|
||||
declare i64 @llvm.objectsize.i64(i8*, i1, i1) nounwind readonly
|
||||
declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1) nounwind readonly
|
||||
declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
|
||||
declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
|
||||
|
||||
declare void @llvm.trap() nounwind
|
||||
|
@ -8,9 +8,9 @@ target datalayout = "p:16:16"
|
||||
; CHECK-LABEL: @alloca_overflow_is_unknown(
|
||||
define i16 @alloca_overflow_is_unknown() {
|
||||
%i = alloca i8, i32 65537
|
||||
%j = call i16 @llvm.objectsize.i16.p0i8(i8* %i, i1 false, i1 false)
|
||||
%j = call i16 @llvm.objectsize.i16.p0i8(i8* %i, i1 false, i1 false, i1 false)
|
||||
; CHECK: ret i16 -1
|
||||
ret i16 %j
|
||||
}
|
||||
|
||||
declare i16 @llvm.objectsize.i16.p0i8(i8*, i1, i1)
|
||||
declare i16 @llvm.objectsize.i16.p0i8(i8*, i1, i1, i1)
|
||||
|
@ -1,18 +1,18 @@
|
||||
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: @objectsize_group_to_flat_i32(
|
||||
; CHECK: %val = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %group.ptr, i1 true, i1 false)
|
||||
; CHECK: %val = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %group.ptr, i1 true, i1 false, i1 false)
|
||||
define i32 @objectsize_group_to_flat_i32(i8 addrspace(3)* %group.ptr) #0 {
|
||||
%cast = addrspacecast i8 addrspace(3)* %group.ptr to i8*
|
||||
%val = call i32 @llvm.objectsize.i32.p0i8(i8* %cast, i1 true, i1 false)
|
||||
%val = call i32 @llvm.objectsize.i32.p0i8(i8* %cast, i1 true, i1 false, i1 false)
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @objectsize_global_to_flat_i64(
|
||||
; CHECK: %val = call i64 @llvm.objectsize.i64.p3i8(i8 addrspace(3)* %global.ptr, i1 true, i1 false)
|
||||
; CHECK: %val = call i64 @llvm.objectsize.i64.p3i8(i8 addrspace(3)* %global.ptr, i1 true, i1 false, i1 false)
|
||||
define i64 @objectsize_global_to_flat_i64(i8 addrspace(3)* %global.ptr) #0 {
|
||||
%cast = addrspacecast i8 addrspace(3)* %global.ptr to i8*
|
||||
%val = call i64 @llvm.objectsize.i64.p0i8(i8* %cast, i1 true, i1 false)
|
||||
%val = call i64 @llvm.objectsize.i64.p0i8(i8* %cast, i1 true, i1 false, i1 false)
|
||||
ret i64 %val
|
||||
}
|
||||
|
||||
@ -134,8 +134,8 @@ define i64 @invalid_variable_volatile_atomicinc_group_to_flat_i64(i64 addrspace(
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) #1
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1) #1
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) #1
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) #1
|
||||
declare i32 @llvm.amdgcn.atomic.inc.i32.p0i32(i32* nocapture, i32, i32, i32, i1) #2
|
||||
declare i64 @llvm.amdgcn.atomic.inc.i64.p0i64(i64* nocapture, i64, i32, i32, i1) #2
|
||||
declare i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* nocapture, i32, i32, i32, i1) #2
|
||||
|
@ -0,0 +1,83 @@
|
||||
; RUN: opt -instcombine -S < %s | FileCheck %s --dump-input-on-failure
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.14.0"
|
||||
|
||||
; Function Attrs: nounwind ssp uwtable
|
||||
define i64 @weird_identity_but_ok(i64 %sz) {
|
||||
entry:
|
||||
%call = tail call i8* @malloc(i64 %sz)
|
||||
%calc_size = tail call i64 @llvm.objectsize.i64.p0i8(i8* %call, i1 false, i1 true, i1 true)
|
||||
tail call void @free(i8* %call)
|
||||
ret i64 %calc_size
|
||||
}
|
||||
|
||||
; CHECK: define i64 @weird_identity_but_ok(i64 %sz)
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i64 %sz
|
||||
; CHECK-NEXT: }
|
||||
|
||||
define i64 @phis_are_neat(i1 %which) {
|
||||
entry:
|
||||
br i1 %which, label %first_label, label %second_label
|
||||
|
||||
first_label:
|
||||
%first_call = call i8* @malloc(i64 10)
|
||||
br label %join_label
|
||||
|
||||
second_label:
|
||||
%second_call = call i8* @malloc(i64 30)
|
||||
br label %join_label
|
||||
|
||||
join_label:
|
||||
%joined = phi i8* [ %first_call, %first_label ], [ %second_call, %second_label ]
|
||||
%calc_size = tail call i64 @llvm.objectsize.i64.p0i8(i8* %joined, i1 false, i1 true, i1 true)
|
||||
ret i64 %calc_size
|
||||
}
|
||||
|
||||
; CHECK: %0 = phi i64 [ 10, %first_label ], [ 30, %second_label ]
|
||||
; CHECK-NEXT: ret i64 %0
|
||||
|
||||
define i64 @internal_pointer(i64 %sz) {
|
||||
entry:
|
||||
%ptr = call i8* @malloc(i64 %sz)
|
||||
%ptr2 = getelementptr inbounds i8, i8* %ptr, i32 2
|
||||
%calc_size = call i64 @llvm.objectsize.i64.p0i8(i8* %ptr2, i1 false, i1 true, i1 true)
|
||||
ret i64 %calc_size
|
||||
}
|
||||
|
||||
; CHECK: define i64 @internal_pointer(i64 %sz)
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: %0 = add i64 %sz, -2
|
||||
; CHECK-NEXT: %1 = icmp ult i64 %sz, 2
|
||||
; CHECK-NEXT: %2 = select i1 %1, i64 0, i64 %0
|
||||
; CHECK-NEXT: ret i64 %2
|
||||
; CHECK-NEXT: }
|
||||
|
||||
define i64 @uses_nullptr_no_fold() {
|
||||
entry:
|
||||
%res = call i64 @llvm.objectsize.i64.p0i8(i8* null, i1 false, i1 true, i1 true)
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; CHECK: %res = call i64 @llvm.objectsize.i64.p0i8(i8* null, i1 false, i1 true, i1 true)
|
||||
|
||||
define i64 @uses_nullptr_fold() {
|
||||
entry:
|
||||
; NOTE: the third parameter to this call is false, unlike above.
|
||||
%res = call i64 @llvm.objectsize.i64.p0i8(i8* null, i1 false, i1 false, i1 true)
|
||||
ret i64 %res
|
||||
}
|
||||
|
||||
; CHECK: ret i64 0
|
||||
|
||||
; Function Attrs: nounwind allocsize(0)
|
||||
declare i8* @malloc(i64)
|
||||
|
||||
declare i8* @get_unknown_buffer()
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @free(i8* nocapture)
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
|
@ -55,7 +55,7 @@ entry:
|
||||
to label %invoke.cont unwind label %lpad
|
||||
|
||||
invoke.cont:
|
||||
; CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %call, i1 false, i1 false)
|
||||
; CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %call, i1 false, i1 false, i1 false)
|
||||
%0 = tail call i64 @llvm.objectsize.i64(i8* %call, i1 false)
|
||||
ret i64 %0
|
||||
|
||||
|
@ -69,7 +69,7 @@ define i32 @test_rauw(i8* %a, i8* %b, i8** %c) {
|
||||
entry:
|
||||
%call49 = call i64 @strlen(i8* %a)
|
||||
%add180 = add i64 %call49, 1
|
||||
%yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false, i1 false)
|
||||
%yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false, i1 false, i1 false)
|
||||
%call50 = call i8* @__memmove_chk(i8* %b, i8* %a, i64 %add180, i64 %yo107)
|
||||
; CHECK: %strlen = call i64 @strlen(i8* %b)
|
||||
; CHECK-NEXT: %strchr2 = getelementptr i8, i8* %b, i64 %strlen
|
||||
@ -87,7 +87,7 @@ entry:
|
||||
declare i8* @__memmove_chk(i8*, i8*, i64, i64)
|
||||
declare i8* @strrchr(i8*, i32)
|
||||
declare i64 @strlen(i8* nocapture)
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1)
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
|
||||
|
||||
declare i8* @__memset_chk(i8*, i32, i64, i64)
|
||||
|
||||
@ -100,7 +100,7 @@ entry:
|
||||
br i1 %cmp, label %cleanup, label %if.end
|
||||
if.end:
|
||||
%bc = bitcast i8* %call to float*
|
||||
%call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false)
|
||||
%call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false, i1 false)
|
||||
%call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) #1
|
||||
br label %cleanup
|
||||
cleanup:
|
||||
@ -114,7 +114,7 @@ cleanup:
|
||||
; CHECK-NEXT: br i1 %cmp, label %cleanup, label %if.end
|
||||
; CHECK: if.end:
|
||||
; CHECK-NEXT: %bc = bitcast i8* %call to float*
|
||||
; CHECK-NEXT: %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false)
|
||||
; CHECK-NEXT: %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false, i1 false)
|
||||
; CHECK-NEXT: %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2)
|
||||
; CHECK-NEXT: br label %cleanup
|
||||
; CHECK: cleanup:
|
||||
|
@ -8,7 +8,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
||||
define i32 @foo() nounwind {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: ret i32 60
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ define i8* @bar() nounwind {
|
||||
; CHECK-LABEL: @bar(
|
||||
entry:
|
||||
%retval = alloca i8*
|
||||
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
%cmp = icmp ne i32 %0, -1
|
||||
; CHECK: br i1 true
|
||||
br i1 %cmp, label %cond.true, label %cond.false
|
||||
@ -33,7 +33,7 @@ cond.false:
|
||||
define i32 @f() nounwind {
|
||||
; CHECK-LABEL: @f(
|
||||
; CHECK-NEXT: ret i32 0
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr ([60 x i8], [60 x i8]* @a, i32 1, i32 0), i1 false, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr ([60 x i8], [60 x i8]* @a, i32 1, i32 0), i1 false, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ define i32 @f() nounwind {
|
||||
define i1 @baz() nounwind {
|
||||
; CHECK-LABEL: @baz(
|
||||
; CHECK-NEXT: objectsize
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 0), i1 false, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
%2 = icmp eq i32 %1, -1
|
||||
ret i1 %2
|
||||
}
|
||||
@ -51,7 +51,7 @@ define void @test1(i8* %q, i32 %x) nounwind noinline {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK: objectsize.i32.p0i8
|
||||
entry:
|
||||
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 10), i1 false, i1 false) ; <i64> [#uses=1]
|
||||
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 10), i1 false, i1 false, i1 false) ; <i64> [#uses=1]
|
||||
%1 = icmp eq i32 %0, -1 ; <i1> [#uses=1]
|
||||
br i1 %1, label %"47", label %"46"
|
||||
|
||||
@ -67,7 +67,7 @@ entry:
|
||||
define i32 @test2() nounwind {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: ret i32 34
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr (i8, i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr (i8, i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -76,9 +76,9 @@ define i32 @test2() nounwind {
|
||||
|
||||
declare i8* @__memcpy_chk(i8*, i8*, i32, i32) nounwind
|
||||
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) nounwind readonly
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) nounwind readonly
|
||||
|
||||
declare i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)*, i1, i1) nounwind readonly
|
||||
declare i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
|
||||
|
||||
declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint
|
||||
|
||||
@ -90,7 +90,7 @@ entry:
|
||||
bb11:
|
||||
%0 = getelementptr inbounds float, float* getelementptr inbounds ([480 x float], [480 x float]* @array, i32 0, i32 128), i32 -127 ; <float*> [#uses=1]
|
||||
%1 = bitcast float* %0 to i8* ; <i8*> [#uses=1]
|
||||
%2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false) ; <i32> [#uses=1]
|
||||
%2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false, i1 false) ; <i32> [#uses=1]
|
||||
%3 = call i8* @__memcpy_chk(i8* undef, i8* undef, i32 512, i32 %2) nounwind ; <i8*> [#uses=0]
|
||||
; CHECK: unreachable
|
||||
unreachable
|
||||
@ -112,7 +112,7 @@ define i32 @test4(i8** %esc) nounwind ssp {
|
||||
entry:
|
||||
%0 = alloca %struct.data, align 8
|
||||
%1 = bitcast %struct.data* %0 to i8*
|
||||
%2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false) nounwind
|
||||
%2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false, i1 false) nounwind
|
||||
; CHECK-NOT: @llvm.objectsize
|
||||
; CHECK: @llvm.memset.p0i8.i32(i8* nonnull align 8 %1, i8 0, i32 1824, i1 false)
|
||||
%3 = call i8* @__memset_chk(i8* %1, i32 0, i32 1824, i32 %2) nounwind
|
||||
@ -127,7 +127,7 @@ define i8* @test5(i32 %n) nounwind ssp {
|
||||
; CHECK-LABEL: @test5(
|
||||
entry:
|
||||
%0 = tail call noalias i8* @malloc(i32 20) nounwind
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false, i1 false)
|
||||
%2 = load i8*, i8** @s, align 8
|
||||
; CHECK-NOT: @llvm.objectsize
|
||||
; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 1 %1, i32 10, i1 false)
|
||||
@ -139,7 +139,7 @@ define void @test6(i32 %n) nounwind ssp {
|
||||
; CHECK-LABEL: @test6(
|
||||
entry:
|
||||
%0 = tail call noalias i8* @malloc(i32 20) nounwind
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false, i1 false)
|
||||
%2 = load i8*, i8** @s, align 8
|
||||
; CHECK-NOT: @llvm.objectsize
|
||||
; CHECK: @__memcpy_chk(i8* %0, i8* %1, i32 30, i32 20)
|
||||
@ -156,7 +156,7 @@ define i32 @test7(i8** %esc) {
|
||||
%alloc = call noalias i8* @malloc(i32 48) nounwind
|
||||
store i8* %alloc, i8** %esc
|
||||
%gep = getelementptr inbounds i8, i8* %alloc, i32 16
|
||||
%objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false) nounwind readonly
|
||||
%objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false, i1 false) nounwind readonly
|
||||
; CHECK: ret i32 32
|
||||
ret i32 %objsize
|
||||
}
|
||||
@ -168,7 +168,7 @@ define i32 @test8(i8** %esc) {
|
||||
%alloc = call noalias i8* @calloc(i32 5, i32 7) nounwind
|
||||
store i8* %alloc, i8** %esc
|
||||
%gep = getelementptr inbounds i8, i8* %alloc, i32 5
|
||||
%objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false) nounwind readonly
|
||||
%objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false, i1 false) nounwind readonly
|
||||
; CHECK: ret i32 30
|
||||
ret i32 %objsize
|
||||
}
|
||||
@ -180,7 +180,7 @@ declare noalias i8* @strndup(i8* nocapture, i32) nounwind
|
||||
define i32 @test9(i8** %esc) {
|
||||
%call = tail call i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0)) nounwind
|
||||
store i8* %call, i8** %esc, align 8
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false)
|
||||
; CHECK: ret i32 8
|
||||
ret i32 %1
|
||||
}
|
||||
@ -189,7 +189,7 @@ define i32 @test9(i8** %esc) {
|
||||
define i32 @test10(i8** %esc) {
|
||||
%call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 3) nounwind
|
||||
store i8* %call, i8** %esc, align 8
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false)
|
||||
; CHECK: ret i32 4
|
||||
ret i32 %1
|
||||
}
|
||||
@ -198,7 +198,7 @@ define i32 @test10(i8** %esc) {
|
||||
define i32 @test11(i8** %esc) {
|
||||
%call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 7) nounwind
|
||||
store i8* %call, i8** %esc, align 8
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false)
|
||||
; CHECK: ret i32 8
|
||||
ret i32 %1
|
||||
}
|
||||
@ -207,7 +207,7 @@ define i32 @test11(i8** %esc) {
|
||||
define i32 @test12(i8** %esc) {
|
||||
%call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 8) nounwind
|
||||
store i8* %call, i8** %esc, align 8
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false)
|
||||
; CHECK: ret i32 8
|
||||
ret i32 %1
|
||||
}
|
||||
@ -216,7 +216,7 @@ define i32 @test12(i8** %esc) {
|
||||
define i32 @test13(i8** %esc) {
|
||||
%call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 57) nounwind
|
||||
store i8* %call, i8** %esc, align 8
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false)
|
||||
%1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false)
|
||||
; CHECK: ret i32 8
|
||||
ret i32 %1
|
||||
}
|
||||
@ -227,7 +227,7 @@ define i32 @test13(i8** %esc) {
|
||||
; CHECK-NEXT: ret i32 60
|
||||
define i32 @test18() {
|
||||
%bc = bitcast [60 x i8]* @globalalias to i8*
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -237,35 +237,35 @@ define i32 @test18() {
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test19() {
|
||||
%bc = bitcast [60 x i8]* @globalalias2 to i8*
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test20(
|
||||
; CHECK: ret i32 0
|
||||
define i32 @test20() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test21(
|
||||
; CHECK: ret i32 0
|
||||
define i32 @test21() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 false)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test22(
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test22() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 true)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 true, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test23(
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test23() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 true)
|
||||
%1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 true, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ define i32 @test23() {
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test24() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false,
|
||||
i1 false)
|
||||
i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ define i32 @test24() {
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test25() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true,
|
||||
i1 false)
|
||||
i1 false, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -290,7 +290,7 @@ define i32 @test25() {
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test26() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false,
|
||||
i1 true)
|
||||
i1 true, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
@ -298,6 +298,6 @@ define i32 @test26() {
|
||||
; CHECK: llvm.objectsize
|
||||
define i32 @test27() {
|
||||
%1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true,
|
||||
i1 true)
|
||||
i1 true, i1 false)
|
||||
ret i32 %1
|
||||
}
|
||||
|
@ -64,10 +64,10 @@ define i8* @test_simplify5() {
|
||||
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0
|
||||
|
||||
; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len)
|
||||
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false)
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)
|
||||
%ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 %len)
|
||||
ret i8* %ret
|
||||
}
|
||||
@ -81,7 +81,7 @@ define i8* @test_simplify6() {
|
||||
; CHECK-NEXT: %strlen = call i32 @strlen(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0))
|
||||
; CHECK-NEXT: %1 = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 %strlen
|
||||
; CHECK-NEXT: ret i8* %1
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false)
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)
|
||||
%ret = call i8* @__stpcpy_chk(i8* %dst, i8* %dst, i32 %len)
|
||||
ret i8* %ret
|
||||
}
|
||||
@ -100,4 +100,4 @@ define i8* @test_no_simplify1() {
|
||||
}
|
||||
|
||||
declare i8* @__stpcpy_chk(i8*, i8*, i32) nounwind
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) nounwind readonly
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) nounwind readonly
|
||||
|
@ -64,10 +64,10 @@ define i8* @test_simplify5() {
|
||||
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0
|
||||
|
||||
; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len)
|
||||
; CHECK-NEXT: ret i8* %1
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false)
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)
|
||||
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len)
|
||||
ret i8* %ret
|
||||
}
|
||||
@ -78,10 +78,10 @@ define i8* @test_simplify6() {
|
||||
; CHECK-LABEL: @test_simplify6(
|
||||
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
|
||||
|
||||
; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false)
|
||||
; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
|
||||
; CHECK-NEXT: %ret = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 %len)
|
||||
; CHECK-NEXT: ret i8* %ret
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false)
|
||||
%len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)
|
||||
%ret = call i8* @__strcpy_chk(i8* %dst, i8* %dst, i32 %len)
|
||||
ret i8* %ret
|
||||
}
|
||||
@ -100,4 +100,4 @@ define i8* @test_no_simplify1() {
|
||||
}
|
||||
|
||||
declare i8* @__strcpy_chk(i8*, i8*, i32) nounwind
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) nounwind readonly
|
||||
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) nounwind readonly
|
||||
|
Loading…
x
Reference in New Issue
Block a user