; Adapted from: https://github.com/matter-labs/era-compiler-llvm/blob/v1.4.0/llvm/lib/Target/EraVM/eravm-stdlib.ll
target datalayout = "e-m:e-p:32:64-p1:32:64-i64:64-i128:128-n32:64-S64"
target triple = "riscv64-unknown-none-elf"
define i256 @__addmod(i256 %arg1, i256 %arg2, i256 %modulo) #0 {
entry:
%is_zero = icmp eq i256 %modulo, 0
br i1 %is_zero, label %return, label %addmod
addmod:
%arg1.fr = freeze i256 %arg1
%arg1m = urem i256 %arg1.fr, %modulo
%arg2m = urem i256 %arg2, %modulo
%sum = add i256 %arg1m, %arg2m
%obit = icmp ult i256 %sum, %arg1m
%sum.mod = urem i256 %sum, %modulo
br i1 %obit, label %overflow, label %return
overflow:
%mod.inv = xor i256 %modulo, -1
%sum1 = add i256 %sum, %mod.inv
%sum.ovf = add i256 %sum1, 1
br label %return
return:
%value = phi i256 [0, %entry], [%sum.mod, %addmod], [%sum.ovf, %overflow]
ret i256 %value
}
define private i256 @__clz(i256 %v) #0 {
entry:
%vs128 = lshr i256 %v, 128
%vs128nz = icmp ne i256 %vs128, 0
%n128 = select i1 %vs128nz, i256 128, i256 256
%va128 = select i1 %vs128nz, i256 %vs128, i256 %v
%vs64 = lshr i256 %va128, 64
%vs64nz = icmp ne i256 %vs64, 0
%clza64 = sub i256 %n128, 64
%n64 = select i1 %vs64nz, i256 %clza64, i256 %n128
%va64 = select i1 %vs64nz, i256 %vs64, i256 %va128
%vs32 = lshr i256 %va64, 32
%vs32nz = icmp ne i256 %vs32, 0
%clza32 = sub i256 %n64, 32
%n32 = select i1 %vs32nz, i256 %clza32, i256 %n64
%va32 = select i1 %vs32nz, i256 %vs32, i256 %va64
%vs16 = lshr i256 %va32, 16
%vs16nz = icmp ne i256 %vs16, 0
%clza16 = sub i256 %n32, 16
%n16 = select i1 %vs16nz, i256 %clza16, i256 %n32
%va16 = select i1 %vs16nz, i256 %vs16, i256 %va32
%vs8 = lshr i256 %va16, 8
%vs8nz = icmp ne i256 %vs8, 0
%clza8 = sub i256 %n16, 8
%n8 = select i1 %vs8nz, i256 %clza8, i256 %n16
%va8 = select i1 %vs8nz, i256 %vs8, i256 %va16
%vs4 = lshr i256 %va8, 4
%vs4nz = icmp ne i256 %vs4, 0
%clza4 = sub i256 %n8, 4
%n4 = select i1 %vs4nz, i256 %clza4, i256 %n8
%va4 = select i1 %vs4nz, i256 %vs4, i256 %va8
%vs2 = lshr i256 %va4, 2
%vs2nz = icmp ne i256 %vs2, 0
%clza2 = sub i256 %n4, 2
%n2 = select i1 %vs2nz, i256 %clza2, i256 %n4
%va2 = select i1 %vs2nz, i256 %vs2, i256 %va4
%vs1 = lshr i256 %va2, 1
%vs1nz = icmp ne i256 %vs1, 0
%clza1 = sub i256 %n2, 2
%clzax = sub i256 %n2, %va2
%result = select i1 %vs1nz, i256 %clza1, i256 %clzax
ret i256 %result
}
define private i256 @__ulongrem(i256 %0, i256 %1, i256 %2) #0 {
%.not = icmp ult i256 %1, %2
br i1 %.not, label %4, label %51
4:
%5 = tail call i256 @__clz(i256 %2)
%.not61 = icmp eq i256 %5, 0
br i1 %.not61, label %13, label %6
6:
%7 = shl i256 %2, %5
%8 = shl i256 %1, %5
%9 = sub nuw nsw i256 256, %5
%10 = lshr i256 %0, %9
%11 = or i256 %10, %8
%12 = shl i256 %0, %5
br label %13
13:
%.054 = phi i256 [ %7, %6 ], [ %2, %4 ]
%.053 = phi i256 [ %11, %6 ], [ %1, %4 ]
%.052 = phi i256 [ %12, %6 ], [ %0, %4 ]
%14 = lshr i256 %.054, 128
%15 = udiv i256 %.053, %14
%16 = urem i256 %.053, %14
%17 = and i256 %.054, 340282366920938463463374607431768211455
%18 = lshr i256 %.052, 128
br label %19
19:
%.056 = phi i256 [ %15, %13 ], [ %25, %.critedge ]
%.055 = phi i256 [ %16, %13 ], [ %26, %.critedge ]
%.not62 = icmp ult i256 %.056, 340282366920938463463374607431768211455
br i1 %.not62, label %20, label %.critedge
20:
%21 = mul nuw i256 %.056, %17
%22 = shl nuw i256 %.055, 128
%23 = or i256 %22, %18
%24 = icmp ugt i256 %21, %23
br i1 %24, label %.critedge, label %27
.critedge:
%25 = add i256 %.056, -1
%26 = add i256 %.055, %14
%.not65 = icmp ult i256 %26, 340282366920938463463374607431768211455
br i1 %.not65, label %19, label %27
27:
%.157 = phi i256 [ %25, %.critedge ], [ %.056, %20 ]
%28 = shl i256 %.053, 128
%29 = or i256 %18, %28
%30 = and i256 %.157, 340282366920938463463374607431768211455
%31 = mul i256 %30, %.054
%32 = sub i256 %29, %31
%33 = udiv i256 %32, %14
%34 = urem i256 %32, %14
%35 = and i256 %.052, 340282366920938463463374607431768211455
br label %36
36:
%.2 = phi i256 [ %33, %27 ], [ %42, %.critedge1 ]
%.1 = phi i256 [ %34, %27 ], [ %43, %.critedge1 ]
%.not63 = icmp ult i256 %.2, 340282366920938463463374607431768211455
br i1 %.not63, label %37, label %.critedge1
37:
%38 = mul nuw i256 %.2, %17
%39 = shl i256 %.1, 128
%40 = or i256 %39, %35
%41 = icmp ugt i256 %38, %40
br i1 %41, label %.critedge1, label %44
.critedge1:
%42 = add i256 %.2, -1
%43 = add i256 %.1, %14
%.not64 = icmp ult i256 %43, 340282366920938463463374607431768211455
br i1 %.not64, label %36, label %44
44:
%.3 = phi i256 [ %42, %.critedge1 ], [ %.2, %37 ]
%45 = shl i256 %32, 128
%46 = or i256 %45, %35
%47 = and i256 %.3, 340282366920938463463374607431768211455
%48 = mul i256 %47, %.054
%49 = sub i256 %46, %48
%50 = lshr i256 %49, %5
br label %51
51:
%.0 = phi i256 [ %50, %44 ], [ -1, %3 ]
ret i256 %.0
}
define i256 @__mulmod(i256 %arg1, i256 %arg2, i256 %modulo) #0 {
entry:
%cccond = icmp eq i256 %modulo, 0
br i1 %cccond, label %ccret, label %entrycont
ccret:
ret i256 0
entrycont:
%arg1m = urem i256 %arg1, %modulo
%arg2m = urem i256 %arg2, %modulo
%less_then_2_128 = icmp ult i256 %modulo, 340282366920938463463374607431768211456
br i1 %less_then_2_128, label %fast, label %slow
fast:
%prod = mul i256 %arg1m, %arg2m
%prodm = urem i256 %prod, %modulo
ret i256 %prodm
slow:
%arg1e = zext i256 %arg1m to i512
%arg2e = zext i256 %arg2m to i512
%prode = mul i512 %arg1e, %arg2e
%prodl = trunc i512 %prode to i256
%prodeh = lshr i512 %prode, 256
%prodh = trunc i512 %prodeh to i256
%res = call i256 @__ulongrem(i256 %prodl, i256 %prodh, i256 %modulo)
ret i256 %res
}
define i256 @__signextend(i256 %numbyte, i256 %value) #0 {
entry:
%is_overflow = icmp uge i256 %numbyte, 31
br i1 %is_overflow, label %return, label %signextend
signextend:
%numbit_byte = mul nuw nsw i256 %numbyte, 8
%numbit = add nsw nuw i256 %numbit_byte, 7
%numbit_inv = sub i256 256, %numbit
%signmask = shl i256 1, %numbit
%valmask = lshr i256 -1, %numbit_inv
%ext1 = shl i256 -1, %numbit
%signv = and i256 %signmask, %value
%sign = icmp ne i256 %signv, 0
%valclean = and i256 %value, %valmask
%sext = select i1 %sign, i256 %ext1, i256 0
%result = or i256 %sext, %valclean
br label %return
return:
%signext_res = phi i256 [%value, %entry], [%result, %signextend]
ret i256 %signext_res
}
define i256 @__exp(i256 %value, i256 %exp) "noinline-oz" #0 {
entry:
%exp_is_non_zero = icmp eq i256 %exp, 0
br i1 %exp_is_non_zero, label %return, label %exponent_loop_body
return:
%exp_res = phi i256 [ 1, %entry ], [ %exp_res.1, %exponent_loop_body ]
ret i256 %exp_res
exponent_loop_body:
%exp_res.2 = phi i256 [ %exp_res.1, %exponent_loop_body ], [ 1, %entry ]
%exp_val = phi i256 [ %exp_val_halved, %exponent_loop_body ], [ %exp, %entry ]
%val_squared.1 = phi i256 [ %val_squared, %exponent_loop_body ], [ %value, %entry ]
%odd_test = and i256 %exp_val, 1
%is_exp_odd = icmp eq i256 %odd_test, 0
%exp_res.1.interm = select i1 %is_exp_odd, i256 1, i256 %val_squared.1
%exp_res.1 = mul i256 %exp_res.1.interm, %exp_res.2
%val_squared = mul i256 %val_squared.1, %val_squared.1
%exp_val_halved = lshr i256 %exp_val, 1
%exp_val_is_less_2 = icmp ult i256 %exp_val, 2
br i1 %exp_val_is_less_2, label %return, label %exponent_loop_body
}
define private i256 @__exp_pow2(i256 %val_log2, i256 %exp) #0 {
entry:
%shift = mul nuw nsw i256 %val_log2, %exp
%is_overflow = icmp ugt i256 %shift, 255
%shift_res = shl nuw i256 1, %shift
%res = select i1 %is_overflow, i256 0, i256 %shift_res
ret i256 %res
}
attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn }