@@ -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.
1517func (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