Skip to content
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
5 changes: 5 additions & 0 deletions driver/cl_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,11 @@ cl::opt<unsigned>
cl::desc("Warn for stack size bigger than the given number"),
cl::value_desc("threshold"));

cl::opt<bool>
enableGetElementPtrNuw("enable-getelementptr-nuw", cl::ZeroOrMore,
cl::desc("enable nuw(no-unsigned-wrap) flag to "
"LLVM's getelementptr insturction"));

#if LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX
cl::list<std::string>
dcomputeTargets("mdcompute-targets", cl::CommaSeparated,
Expand Down
2 changes: 2 additions & 0 deletions driver/cl_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ extern cl::opt<std::string> saveOptimizationRecord;

extern cl::opt<unsigned> fWarnStackSize;

extern cl::opt<bool> enableGetElementPtrNuw;

#if LDC_LLVM_SUPPORTED_TARGET_SPIRV || LDC_LLVM_SUPPORTED_TARGET_NVPTX
extern cl::list<std::string> dcomputeTargets;
extern cl::opt<std::string> dcomputeFilePrefix;
Expand Down
18 changes: 16 additions & 2 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "dmd/init.h"
#include "dmd/module.h"
#include "dmd/template.h"
#include "driver/cl_options.h"
#include "gen/abi/abi.h"
#include "gen/arrays.h"
#include "gen/classes.h"
Expand Down Expand Up @@ -1868,9 +1869,18 @@ DLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,

LLValue *ptr = src;
LLType * ty = nullptr;
#if LDC_LLVM_VER >= 2000
llvm::GEPNoWrapFlags nw = llvm::GEPNoWrapFlags::inBounds();
if (opts::enableGetElementPtrNuw)
nw |= llvm::GEPNoWrapFlags::noUnsignedWrap();
#endif
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, nw
#endif
);
ty = DtoType(vd->type);
} else {
if (ad->structsize == 0) { // can happen for extern(C) structs
Expand All @@ -1884,7 +1894,11 @@ 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, nw
#endif
);
ty = isaStruct(st)->getElementType(off);
}
}
Expand Down
24 changes: 21 additions & 3 deletions gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "dmd/root/rmem.h"
#include "dmd/target.h"
#include "dmd/template.h"
#include "driver/cl_options.h"
#include "gen/aa.h"
#include "gen/abi/abi.h"
#include "gen/arrays.h"
Expand Down Expand Up @@ -1198,7 +1199,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 && opts::enableGetElementPtrNuw)
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 @@ -1292,8 +1302,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 && opts::enableGetElementPtrNuw)
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
8 changes: 4 additions & 4 deletions tests/codegen/inbounds.d
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %ldc -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
// RUN: %ldc -enable-getelementptr-nuw -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll

struct S {
float x, y;
Expand All @@ -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