Skip to content

Emit getelementptr inbounds nuw flag where possible #4936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1860,7 +1860,12 @@ DLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
LLType * ty = nullptr;
if (!isFieldIdx) {
// apply byte-wise offset from object start
ptr = DtoGEP1(getI8Type(), ptr, off);
ptr = DtoGEP1(getI8Type(), ptr, off
#if LDC_LLVM_VER >= 2000
, "", nullptr
, llvm::GEPNoWrapFlags::inBounds() | llvm::GEPNoWrapFlags::noUnsignedWrap()
#endif
);
ty = DtoType(vd->type);
} else {
if (ad->structsize == 0) { // can happen for extern(C) structs
Expand All @@ -1874,7 +1879,12 @@ DLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
} else {
st = irTypeAggr->getLLType();
}
ptr = DtoGEP(st, ptr, 0, off);
ptr = DtoGEP(st, ptr, 0, off
#if LDC_LLVM_VER >= 2000
, "", nullptr
, llvm::GEPNoWrapFlags::inBounds() | llvm::GEPNoWrapFlags::noUnsignedWrap()
#endif
);
ty = isaStruct(st)->getElementType(off);
}
}
Expand Down
23 changes: 20 additions & 3 deletions gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,16 @@ class ToElemVisitor : public Visitor {
}
LLType *elt = DtoMemType(e1type->nextOf());
LLType *arrty = llvm::ArrayType::get(elt, e1type->isTypeSArray()->dim->isIntegerExp()->getInteger());
arrptr = DtoGEP(arrty, DtoLVal(l), DtoConstUint(0), DtoRVal(r));
#if LDC_LLVM_VER >= 2000
llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds();
if (e->indexIsInBounds)
nw |= llvm::GEPNoWrapFlags::noUnsignedWrap();
#endif
arrptr = DtoGEP(arrty, DtoLVal(l), DtoConstUint(0), DtoRVal(r)
#if LDC_LLVM_VER >= 2000
, "", nullptr, nw
#endif
);
} else if (e1type->ty == TY::Tarray) {
if (p->emitArrayBoundsChecks() && !e->indexIsInBounds) {
DtoIndexBoundsCheck(e->loc, l, r);
Expand Down Expand Up @@ -1284,8 +1293,16 @@ class ToElemVisitor : public Visitor {
}

// offset by lower
eptr = DtoGEP1(DtoMemType(etype->nextOf()), getBasePointer(), vlo, "lowerbound");

#if LDC_LLVM_VER >= 2000
llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds();
if (!needCheckUpper && !needCheckLower)
nw |= llvm::GEPNoWrapFlags::noUnsignedWrap();
#endif
eptr = DtoGEP1(DtoMemType(etype->nextOf()), getBasePointer(), vlo, "lowerbound"
#if LDC_LLVM_VER >= 2000
, nullptr, nw
#endif
);
// adjust length
elen = p->ir->CreateSub(vup, vlo);
}
Expand Down
87 changes: 72 additions & 15 deletions gen/tollvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,46 +357,103 @@ LLIntegerType *DtoSize_t() {
namespace {
llvm::GetElementPtrInst *DtoGEP(LLType *pointeeTy, LLValue *ptr,
llvm::ArrayRef<LLValue *> indices,
const char *name, llvm::BasicBlock *bb) {
const char *name, llvm::BasicBlock *bb
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
auto gep = llvm::GetElementPtrInst::Create(pointeeTy, ptr, indices, name,
bb ? bb : gIR->scopebb());
#if LDC_LLVM_VER >= 2000
gep->setNoWrapFlags(nw);
#else
gep->setIsInBounds(true);
#endif
return gep;
}
}

LLValue *DtoGEP1(LLType *pointeeTy, LLValue *ptr, LLValue *i0, const char *name,
llvm::BasicBlock *bb) {
return DtoGEP(pointeeTy, ptr, i0, name, bb);
llvm::BasicBlock *bb
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
return DtoGEP(pointeeTy, ptr, i0, name, bb
#if LDC_LLVM_VER >= 2000
, nw
#endif
);
}

LLValue *DtoGEP(LLType *pointeeTy, LLValue *ptr, LLValue *i0, LLValue *i1,
const char *name, llvm::BasicBlock *bb) {
const char *name, llvm::BasicBlock *bb
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
LLValue *indices[] = {i0, i1};
return DtoGEP(pointeeTy, ptr, indices, name, bb);
return DtoGEP(pointeeTy, ptr, indices, name, bb
#if LDC_LLVM_VER >= 2000
, nw
#endif
);
}

LLValue *DtoGEP1(LLType *pointeeTy, LLValue *ptr, unsigned i0, const char *name,
llvm::BasicBlock *bb) {
return DtoGEP(pointeeTy, ptr, DtoConstUint(i0), name, bb);
llvm::BasicBlock *bb
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
return DtoGEP(pointeeTy, ptr, DtoConstUint(i0), name, bb
#if LDC_LLVM_VER >= 2000
, nw
#endif
);
}

LLValue *DtoGEP(LLType *pointeeTy, LLValue *ptr, unsigned i0, unsigned i1,
const char *name, llvm::BasicBlock *bb) {
const char *name, llvm::BasicBlock *bb
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
LLValue *indices[] = {DtoConstUint(i0), DtoConstUint(i1)};
return DtoGEP(pointeeTy, ptr, indices, name, bb);
return DtoGEP(pointeeTy, ptr, indices, name, bb
#if LDC_LLVM_VER >= 2000
, nw
#endif
);
}

LLConstant *DtoGEP(LLType *pointeeTy, LLConstant *ptr, unsigned i0,
unsigned i1) {
unsigned i1
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
LLValue *indices[] = {DtoConstUint(i0), DtoConstUint(i1)};
return llvm::ConstantExpr::getGetElementPtr(pointeeTy, ptr, indices,
/* InBounds = */ true);
#if LDC_LLVM_VER >= 2000
nw
#else
/* InBounds = */ true
#endif
);
}

LLValue *DtoGEP1i64(LLType *pointeeTy, LLValue *ptr, uint64_t i0, const char *name,
llvm::BasicBlock *bb) {
return DtoGEP(pointeeTy, ptr, DtoConstUlong(i0), name, bb);
llvm::BasicBlock *bb
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw
#endif
) {
return DtoGEP(pointeeTy, ptr, DtoConstUlong(i0), name, bb
#if LDC_LLVM_VER >= 2000
, nw
#endif
);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -701,7 +758,7 @@ LLGlobalVariable *makeGlobal(LLStringRef name, LLType* type, LLStringRef section

if (!section.empty())
var->setSection(section);

return var;
}

Expand Down Expand Up @@ -737,7 +794,7 @@ LLGlobalVariable *makeGlobalWithBytes(LLStringRef name, LLConstantList packedCon
0u,
externInit
);

return var;
}

Expand Down
36 changes: 30 additions & 6 deletions gen/tollvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,43 @@ LLStructType *DtoModuleReferenceType();

// getelementptr helpers
LLValue *DtoGEP1(LLType *pointeeTy, LLValue *ptr, LLValue *i0,
const char *name = "", llvm::BasicBlock *bb = nullptr);
const char *name = "", llvm::BasicBlock *bb = nullptr
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds()
#endif
);
LLValue *DtoGEP(LLType *pointeeTy, LLValue *ptr, LLValue *i0, LLValue *i1,
const char *name = "", llvm::BasicBlock *bb = nullptr);
const char *name = "", llvm::BasicBlock *bb = nullptr
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds()
#endif
);

LLValue *DtoGEP1(LLType *pointeeTy, LLValue *ptr, unsigned i0,
const char *name = "", llvm::BasicBlock *bb = nullptr);
const char *name = "", llvm::BasicBlock *bb = nullptr
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds()
#endif
);
LLValue *DtoGEP(LLType *pointeeTy, LLValue *ptr, unsigned i0, unsigned i1,
const char *name = "", llvm::BasicBlock *bb = nullptr);
const char *name = "", llvm::BasicBlock *bb = nullptr
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds()
#endif
);
LLConstant *DtoGEP(LLType *pointeeTy, LLConstant *ptr, unsigned i0,
unsigned i1);
unsigned i1
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds()
#endif
);

LLValue *DtoGEP1i64(LLType *pointeeTy, LLValue *ptr, uint64_t i0,
const char *name = "", llvm::BasicBlock *bb = nullptr);
const char *name = "", llvm::BasicBlock *bb = nullptr
#if LDC_LLVM_VER >= 2000
, llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds()
#endif
);

// to constant helpers
LLConstantInt *DtoConstSize_t(uint64_t);
Expand Down
6 changes: 3 additions & 3 deletions tests/codegen/inbounds.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern(C): // Avoid name mangling
// IndexExp in static array with const exp
// CHECK-LABEL: @foo1
int foo1(int[3] a) {
// CHECK: getelementptr inbounds [3 x i32]
// CHECK: getelementptr inbounds{{( nuw)?}} [3 x i32]
return a[1];
}

Expand Down Expand Up @@ -58,7 +58,7 @@ int foo7(int* p, int i) {
// Struct field
// CHECK-LABEL: @foo8
float foo8(S s) {
// CHECK: getelementptr inbounds
// CHECK: getelementptr inbounds{{( nuw)?}}
return s.y;
}

Expand All @@ -79,7 +79,7 @@ int foo10(int[] a, int i) {
// SliceExp for static array with const lower bound
// CHECK-LABEL: @foo11
int[] foo11(ref int[3] a) {
// CHECK: getelementptr inbounds i32, ptr
// CHECK: getelementptr inbounds{{( nuw)?}} i32, ptr
return a[1 .. $];
}

Expand Down
Loading