compiler: mark all GEPs as inbounds
In Go, it is not possible to construct pointers that are out of bounds (and not null), so let LLVM know about this fact. This leads to a significant code size reduction, around 3% in many cases.
Этот коммит содержится в:
родитель
d155e31b64
коммит
9a3d0683b3
3 изменённых файлов: 21 добавлений и 17 удалений
|
@ -1324,7 +1324,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), uint64(expr.Field), false),
|
||||
}
|
||||
return c.builder.CreateGEP(val, indices, ""), nil
|
||||
return c.builder.CreateInBoundsGEP(val, indices, ""), nil
|
||||
}
|
||||
case *ssa.Function:
|
||||
panic("function is not an expression")
|
||||
|
@ -1344,7 +1344,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
alloca := c.builder.CreateAlloca(array.Type(), "index.alloca")
|
||||
c.builder.CreateStore(array, alloca)
|
||||
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
||||
ptr := c.builder.CreateGEP(alloca, []llvm.Value{zero, index}, "index.gep")
|
||||
ptr := c.builder.CreateInBoundsGEP(alloca, []llvm.Value{zero, index}, "index.gep")
|
||||
return c.builder.CreateLoad(ptr, "index.load"), nil
|
||||
case *ssa.IndexAddr:
|
||||
val := c.getValue(frame, expr.X)
|
||||
|
@ -1385,9 +1385,9 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
index,
|
||||
}
|
||||
return c.builder.CreateGEP(bufptr, indices, ""), nil
|
||||
return c.builder.CreateInBoundsGEP(bufptr, indices, ""), nil
|
||||
case *types.Slice:
|
||||
return c.builder.CreateGEP(bufptr, []llvm.Value{index}, ""), nil
|
||||
return c.builder.CreateInBoundsGEP(bufptr, []llvm.Value{index}, ""), nil
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
@ -1407,7 +1407,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
|
||||
// Lookup byte
|
||||
buf := c.builder.CreateExtractValue(value, 0, "")
|
||||
bufPtr := c.builder.CreateGEP(buf, []llvm.Value{index}, "")
|
||||
bufPtr := c.builder.CreateInBoundsGEP(buf, []llvm.Value{index}, "")
|
||||
return c.builder.CreateLoad(bufPtr, ""), nil
|
||||
case *types.Map:
|
||||
valueType := expr.Type()
|
||||
|
@ -1608,7 +1608,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
}
|
||||
|
||||
sliceLen := c.builder.CreateSub(high, low, "slice.len")
|
||||
slicePtr := c.builder.CreateGEP(value, indices, "slice.ptr")
|
||||
slicePtr := c.builder.CreateInBoundsGEP(value, indices, "slice.ptr")
|
||||
sliceCap := c.builder.CreateSub(llvmLen, low, "slice.cap")
|
||||
|
||||
slice := c.ctx.ConstStruct([]llvm.Value{
|
||||
|
@ -1641,7 +1641,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
high = c.builder.CreateTrunc(high, c.uintptrType, "")
|
||||
}
|
||||
|
||||
newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "")
|
||||
newPtr := c.builder.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "")
|
||||
newLen := c.builder.CreateSub(high, low, "")
|
||||
newCap := c.builder.CreateSub(oldCap, low, "")
|
||||
slice := c.ctx.ConstStruct([]llvm.Value{
|
||||
|
@ -1676,7 +1676,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
|||
high = c.builder.CreateTrunc(high, c.uintptrType, "")
|
||||
}
|
||||
|
||||
newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "")
|
||||
newPtr := c.builder.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "")
|
||||
newLen := c.builder.CreateSub(high, low, "")
|
||||
str := llvm.Undef(c.mod.GetTypeByName("runtime._string"))
|
||||
str = c.builder.CreateInsertValue(str, newPtr, 0, "")
|
||||
|
@ -2119,7 +2119,11 @@ func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, p
|
|||
// This pointer can be calculated from the original
|
||||
// ptrtoint instruction with a GEP. The leftover inttoptr
|
||||
// instruction is trivial to optimize away.
|
||||
return c.builder.CreateGEP(origptr, []llvm.Value{index}, ""), nil
|
||||
// Making it an in bounds GEP even though it's easy to
|
||||
// create a GEP that is not in bounds. However, we're
|
||||
// talking about unsafe code here so the programmer has to
|
||||
// be careful anyway.
|
||||
return c.builder.CreateInBoundsGEP(origptr, []llvm.Value{index}, ""), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,13 +172,13 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
|||
// stack = stack.next
|
||||
// switch stack.callback {
|
||||
c.builder.SetInsertPointAtEnd(loop)
|
||||
nextStackGEP := c.builder.CreateGEP(deferData, []llvm.Value{
|
||||
nextStackGEP := c.builder.CreateInBoundsGEP(deferData, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 1, false), // .next field
|
||||
}, "stack.next.gep")
|
||||
nextStack := c.builder.CreateLoad(nextStackGEP, "stack.next")
|
||||
c.builder.CreateStore(nextStack, frame.deferPtr)
|
||||
gep := c.builder.CreateGEP(deferData, []llvm.Value{
|
||||
gep := c.builder.CreateInBoundsGEP(deferData, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false), // .callback field
|
||||
}, "callback.gep")
|
||||
|
@ -211,7 +211,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
|||
forwardParams := []llvm.Value{}
|
||||
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
||||
for i := 2; i < len(valueTypes); i++ {
|
||||
gep := c.builder.CreateGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false)}, "gep")
|
||||
gep := c.builder.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false)}, "gep")
|
||||
forwardParam := c.builder.CreateLoad(gep, "param")
|
||||
forwardParams = append(forwardParams, forwardParam)
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
|||
forwardParams := []llvm.Value{}
|
||||
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
||||
for i := range callback.Params {
|
||||
gep := c.builder.CreateGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(c.ctx.Int32Type(), uint64(i+2), false)}, "gep")
|
||||
gep := c.builder.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(c.ctx.Int32Type(), uint64(i+2), false)}, "gep")
|
||||
forwardParam := c.builder.CreateLoad(gep, "param")
|
||||
forwardParams = append(forwardParams, forwardParam)
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
|||
forwardParams := []llvm.Value{}
|
||||
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
||||
for i := 2; i < len(valueTypes); i++ {
|
||||
gep := c.builder.CreateGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false)}, "")
|
||||
gep := c.builder.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false)}, "")
|
||||
forwardParam := c.builder.CreateLoad(gep, "param")
|
||||
forwardParams = append(forwardParams, forwardParam)
|
||||
}
|
||||
|
|
|
@ -485,7 +485,7 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
|
|||
llvm.ConstInt(c.ctx.Int1Type(), 0, false),
|
||||
}, "task.promise.raw")
|
||||
promise := c.builder.CreateBitCast(promiseRaw, llvm.PointerType(promiseType, 0), "task.promise")
|
||||
dataPtr := c.builder.CreateGEP(promise, []llvm.Value{
|
||||
dataPtr := c.builder.CreateInBoundsGEP(promise, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 2, false),
|
||||
}, "task.promise.data")
|
||||
|
@ -546,13 +546,13 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
|
|||
llvm.ConstInt(c.ctx.Int1Type(), 0, false),
|
||||
}, "task.promise.raw")
|
||||
promise := c.builder.CreateBitCast(promiseRaw, llvm.PointerType(promiseType, 0), "task.promise")
|
||||
dataPtr := c.builder.CreateGEP(promise, []llvm.Value{
|
||||
dataPtr := c.builder.CreateInBoundsGEP(promise, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 2, false),
|
||||
}, "task.promise.data")
|
||||
valueAlloca.ReplaceAllUsesWith(c.builder.CreateBitCast(dataPtr, valueAlloca.Type(), ""))
|
||||
valueAlloca.EraseFromParentAsInstruction()
|
||||
commaOkPtr := c.builder.CreateGEP(promise, []llvm.Value{
|
||||
commaOkPtr := c.builder.CreateInBoundsGEP(promise, []llvm.Value{
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||
llvm.ConstInt(c.ctx.Int32Type(), 1, false),
|
||||
}, "task.promise.comma-ok")
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче