Skip to content

Commit b864663

Browse files
committed
compiler: unroll small array hash/equal instead of looping
1 parent f46da5a commit b864663

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

compiler/map.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"tinygo.org/x/go-llvm"
1111
)
1212

13+
const hashArrayUnrollLimit = 4
14+
1315
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
1416
// initializing an appropriately sized object.
1517
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
@@ -559,8 +561,17 @@ func (b *builder) generateKeyHash(keyType types.Type, llvmKeyType llvm.Type, key
559561
if arrayLen == 0 {
560562
return llvm.ConstInt(b.ctx.Int32Type(), 0, false)
561563
}
562-
// Non-binary elements: generate a loop to avoid code explosion
563-
// for large arrays.
564+
if arrayLen <= hashArrayUnrollLimit {
565+
hash := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
566+
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
567+
for i := 0; i < int(arrayLen); i++ {
568+
idx := llvm.ConstInt(b.uintptrType, uint64(i), false)
569+
elemPtr := b.CreateInBoundsGEP(llvmKeyType, keyPtr, []llvm.Value{zero, idx}, "")
570+
elemHash := b.generateKeyHash(elemType, llvmElemType, elemPtr, seed)
571+
hash = b.CreateXor(hash, elemHash, "")
572+
}
573+
return hash
574+
}
564575
initHash := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
565576
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
566577

@@ -672,7 +683,18 @@ func (b *builder) generateKeyEqual(keyType types.Type, llvmKeyType llvm.Type, xP
672683
if arrayLen == 0 {
673684
return llvm.ConstInt(b.ctx.Int1Type(), 1, false)
674685
}
675-
// Non-binary elements: generate a loop with short-circuit exit.
686+
if arrayLen <= hashArrayUnrollLimit {
687+
result := llvm.ConstInt(b.ctx.Int1Type(), 1, false)
688+
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
689+
for i := 0; i < int(arrayLen); i++ {
690+
idx := llvm.ConstInt(b.uintptrType, uint64(i), false)
691+
xElemPtr := b.CreateInBoundsGEP(llvmKeyType, xPtr, []llvm.Value{zero, idx}, "")
692+
yElemPtr := b.CreateInBoundsGEP(llvmKeyType, yPtr, []llvm.Value{zero, idx}, "")
693+
elemEq := b.generateKeyEqual(elemType, llvmElemType, xElemPtr, yElemPtr, fn)
694+
result = b.CreateAnd(result, elemEq, "")
695+
}
696+
return result
697+
}
676698
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
677699

678700
loopEntry := b.GetInsertBlock()

0 commit comments

Comments
 (0)