ysbaddaden / nanolib.cr

16 stars 0 forks source link

Custom primitives to disable binary ops across int/float sizes #1

Open ysbaddaden opened 1 month ago

ysbaddaden commented 1 month ago

The current primitives.cr in crystal always define cross integer and float sizes binary operations. I'd like to disable that in nano, and only have binary operations across same type & sizes, only keeping the checked & unchecked conversions. We could then bring them back on demand.

Note: I wonder why cross type operations are primitives, they could be handled in stdlib only:

struct Int32
  @[AlwaysInline]
  def +(other : Int8) : Int32
    self + other.to_i32!
  end
end
straight-shoota commented 1 month ago

I wonder why cross type operations are primitives, they could be handled in stdlib only.

LLVM exposes cross-size operations directly, so it's quite easily available. Maybe there's some efficiency benefit? Although I would expect the optimizer to handle this as well. But maybe primitives are more performant without optimizations?

ysbaddaden commented 1 month ago

The LLVM IR looks identical to the above crystal code (cast then add), optimized or not (using unchecked math for brevity):

@[NoInline]
def add(a : Int32, other : Int8) : Int32
  a &+ other
end
define i32 @"*add<Int32, Int8>:Int32"(i32 %a, i8 %other) #3 {
entry:
  %0 = sext i8 %other to i32
  %1 = add i32 %a, %0
  ret i32 %1
}

Maybe it's more efficient compile-time wise to always generate the LLVM code in place (inlined), than creating lots of methods to be typed, then inlined :thinking: