NilFoundation/zkllvm-assigner

Support overflow intrisics

Opened this issue · 0 comments

llvm.sadd.with.overflow.*

llvm.uadd.with.overflow.*

llvm.ssub.with.overflow.*

llvm.usub.with.overflow.*

llvm.smul.with.overflow.*

llvm.umul.with.overflow.*

clang generate @llvm.umul.with.overflow.i64 which is not supported by assigner on the follow example

[[circuit]] int func(const int num) {
    int* out = new int[num];
    for (int i = 0; i < num; i++) {
        out[i] = num * 3 + 1;
    }
    int x = 0;
    for (int i = 0; i < num; i++) {
        x += out[i];
    }
    return x;
}

IR

; ModuleID = 'for.cpp'
source_filename = "for.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "assigner"

; Function Attrs: circuit mustprogress
define dso_local noundef i32 @_Z4funci(i32 noundef %0) local_unnamed_addr #0 {
  %2 = sext i32 %0 to i64
  %3 = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %2, i64 4)
  %4 = extractvalue { i64, i1 } %3, 1
  %5 = extractvalue { i64, i1 } %3, 0
  %6 = select i1 %4, i64 -1, i64 %5
  %7 = tail call noalias noundef nonnull i8* @_Znam(i64 noundef %6) #3
  %8 = bitcast i8* %7 to i32*
  %9 = icmp slt i32 0, %0
  br i1 %9, label %10, label %13

10:                                               ; preds = %1
  %11 = mul nsw i32 %0, 3
  %12 = add nsw i32 %11, 1
  br label %15

13:                                               ; preds = %15, %1
  %14 = icmp slt i32 0, %0
  br i1 %14, label %23, label %21

15:                                               ; preds = %10, %15
  %16 = phi i32 [ %19, %15 ], [ 0, %10 ]
  %17 = sext i32 %16 to i64
  %18 = getelementptr inbounds i32, i32* %8, i64 %17
  store i32 %12, i32* %18, align 4, !tbaa !3
  %19 = add nsw i32 %16, 1
  %20 = icmp slt i32 %19, %0
  br i1 %20, label %15, label %13, !llvm.loop !7

21:                                               ; preds = %23, %13
  %22 = phi i32 [ 0, %13 ], [ %29, %23 ]
  ret i32 %22

23:                                               ; preds = %13, %23
  %24 = phi i32 [ %30, %23 ], [ 0, %13 ]
  %25 = phi i32 [ %29, %23 ], [ 0, %13 ]
  %26 = sext i32 %24 to i64
  %27 = getelementptr inbounds i32, i32* %8, i64 %26
  %28 = load i32, i32* %27, align 4, !tbaa !3
  %29 = add nsw i32 %25, %28
  %30 = add nsw i32 %24, 1
  %31 = icmp slt i32 %30, %0
  br i1 %31, label %23, label %21, !llvm.loop !10
}

; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare { i64, i1 } @llvm.umul.with.overflow.i64(i64, i64) #1

"for.cpp.ll" 77L, 3053B