Source Code

int test(int a, int b)
{
    return a + b;
}

Frontend lower to LLVM IR (after optimization)

%0 = add i32 %a, %b, !overflow.signedness !0
ret i32 %0

!0 = !{i1 true, !"test.cpp", i32 63, i32 14}

Convert metadata to custom intrinsic

%0 = call i32 @llvm.sadd.with.hw.overflow.i32(i32 %a, i32 %b)
ret i32 %0

Lower to assembly

mov	eax, edi
cs add	eax, esi
ret

Execution

cs add: check signed overflow in hardware, infer 32-bit from register

Convert metadata to UBSan checks (for coverage test)

entry:
  %0 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
  %1 = extractvalue { i32, i1 } %0, 0
  %2 = extractvalue { i32, i1 } %0, 1
  br i1 %2, label %overflow_check, label %5

overflow_check:                                   ; preds = %entry
  %3 = zext i32 %a to i64
  %4 = zext i32 %b to i64
  call void @__ubsan_handle_add_overflow(ptr @overflow.loc, i64 %3, i64 %4)
  br label %5

5:                                                ; preds = %overflow_check, %entry
  ret i32 %1

@.str.overflow = private constant [9 x i8] c"test.cpp\00"
@overflow.loc = private constant %SourceLocation { ptr @.str.overflow, i32 63, i32 14 }