transform: optimize string comparisons against ""
This optimizes a common pattern like: if s != "" { ... } to: if len(s) != 0 { ... } This avoids a runtime call and thus produces slightly better code.
Этот коммит содержится в:
родитель
13db2c13e5
коммит
f9865a08bc
5 изменённых файлов: 77 добавлений и 0 удалений
|
@ -97,6 +97,7 @@ func Optimize(mod llvm.Module, config *compileopts.Config, optLevel, sizeLevel i
|
||||||
// Run TinyGo-specific interprocedural optimizations.
|
// Run TinyGo-specific interprocedural optimizations.
|
||||||
OptimizeAllocs(mod)
|
OptimizeAllocs(mod)
|
||||||
OptimizeStringToBytes(mod)
|
OptimizeStringToBytes(mod)
|
||||||
|
OptimizeStringEqual(mod)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Must be run at any optimization level.
|
// Must be run at any optimization level.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package transform
|
package transform
|
||||||
|
|
||||||
|
// This file implements several small optimizations of runtime calls.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
@ -55,3 +57,31 @@ func OptimizeStringToBytes(mod llvm.Module) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OptimizeStringEqual transforms runtime.stringEqual(...) calls into simple
|
||||||
|
// integer comparisons if at least one of the sides of the comparison is zero.
|
||||||
|
// Ths converts str == "" into len(str) == 0 and "" == "" into false.
|
||||||
|
func OptimizeStringEqual(mod llvm.Module) {
|
||||||
|
stringEqual := mod.NamedFunction("runtime.stringEqual")
|
||||||
|
if stringEqual.IsNil() {
|
||||||
|
// nothing to optimize
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := mod.Context().NewBuilder()
|
||||||
|
defer builder.Dispose()
|
||||||
|
|
||||||
|
for _, call := range getUses(stringEqual) {
|
||||||
|
str1len := call.Operand(1)
|
||||||
|
str2len := call.Operand(3)
|
||||||
|
|
||||||
|
zero := llvm.ConstInt(str1len.Type(), 0, false)
|
||||||
|
if str1len == zero || str2len == zero {
|
||||||
|
builder.SetInsertPointBefore(call)
|
||||||
|
icmp := builder.CreateICmp(llvm.IntEQ, str1len, str2len, "")
|
||||||
|
call.ReplaceAllUsesWith(icmp)
|
||||||
|
call.EraseFromParentAsInstruction()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,3 +13,11 @@ func TestOptimizeStringToBytes(t *testing.T) {
|
||||||
OptimizeStringToBytes(mod)
|
OptimizeStringToBytes(mod)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOptimizeStringEqual(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
testTransform(t, "testdata/stringequal", func(mod llvm.Module) {
|
||||||
|
// Run optimization pass.
|
||||||
|
OptimizeStringEqual(mod)
|
||||||
|
})
|
||||||
|
}
|
19
transform/testdata/stringequal.ll
предоставленный
Обычный файл
19
transform/testdata/stringequal.ll
предоставленный
Обычный файл
|
@ -0,0 +1,19 @@
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
|
||||||
|
target triple = "armv7m-none-eabi"
|
||||||
|
|
||||||
|
@zeroString = constant [0 x i8] zeroinitializer
|
||||||
|
|
||||||
|
declare i1 @runtime.stringEqual(i8*, i32, i8*, i32, i8*, i8*)
|
||||||
|
|
||||||
|
define i1 @main.stringCompareEqualConstantZero(i8* %s1.data, i32 %s1.len, i8* %context, i8* %parentHandle) {
|
||||||
|
entry:
|
||||||
|
%0 = call i1 @runtime.stringEqual(i8* %s1.data, i32 %s1.len, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @zeroString, i32 0, i32 0), i32 0, i8* undef, i8* null)
|
||||||
|
ret i1 %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @main.stringCompareUnequalConstantZero(i8* %s1.data, i32 %s1.len, i8* %context, i8* %parentHandle) {
|
||||||
|
entry:
|
||||||
|
%0 = call i1 @runtime.stringEqual(i8* %s1.data, i32 %s1.len, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @zeroString, i32 0, i32 0), i32 0, i8* undef, i8* null)
|
||||||
|
%1 = xor i1 %0, true
|
||||||
|
ret i1 %1
|
||||||
|
}
|
19
transform/testdata/stringequal.out.ll
предоставленный
Обычный файл
19
transform/testdata/stringequal.out.ll
предоставленный
Обычный файл
|
@ -0,0 +1,19 @@
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
|
||||||
|
target triple = "armv7m-none-eabi"
|
||||||
|
|
||||||
|
@zeroString = constant [0 x i8] zeroinitializer
|
||||||
|
|
||||||
|
declare i1 @runtime.stringEqual(i8*, i32, i8*, i32, i8*, i8*)
|
||||||
|
|
||||||
|
define i1 @main.stringCompareEqualConstantZero(i8* %s1.data, i32 %s1.len, i8* %context, i8* %parentHandle) {
|
||||||
|
entry:
|
||||||
|
%0 = icmp eq i32 %s1.len, 0
|
||||||
|
ret i1 %0
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @main.stringCompareUnequalConstantZero(i8* %s1.data, i32 %s1.len, i8* %context, i8* %parentHandle) {
|
||||||
|
entry:
|
||||||
|
%0 = icmp eq i32 %s1.len, 0
|
||||||
|
%1 = xor i1 %0, true
|
||||||
|
ret i1 %1
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче