-
Notifications
You must be signed in to change notification settings - Fork 14.5k
Closed
Closed
Copy link
Labels
clang:codegenIR generation bugs: mangling, exceptions, etc.IR generation bugs: mangling, exceptions, etc.compiler-rt:ubsanUndefined behavior sanitizerUndefined behavior sanitizermissed-optimization
Description
Consider the following case: https://godbolt.org/z/zxxn3oG1z
; bin/clang -O3 -fsanitize=undefined -S -emit-llvm -o -
int test(int &a, short &c) {
a += c;
return c;
}
@.src = private unnamed_addr constant [17 x i8] c"/app/example.cpp\00", align 1
@0 = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" }
@1 = private unnamed_addr global { { ptr, i32, i32 }, ptr } { { ptr, i32, i32 } { ptr @.src, i32 2, i32 7 }, ptr @0 }
define dso_local noundef range(i32 -32768, 32768) i32 @test(int&, short&)(ptr noundef nonnull align 4 captures(none) dereferenceable(4) %a, ptr noundef nonnull readonly align 2 captures(none) dereferenceable(2) %c) local_unnamed_addr #0 {
entry:
%0 = load i16, ptr %c, align 2
%conv = sext i16 %0 to i32
%1 = load i32, ptr %a, align 4
%2 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %1, i32 %conv)
%3 = extractvalue { i32, i1 } %2, 1
br i1 %3, label %handler.add_overflow, label %cont
handler.add_overflow:
%4 = zext i32 %1 to i64
%5 = zext i32 %conv to i64
tail call void @__ubsan_handle_add_overflow(ptr nonnull @1, i64 %4, i64 %5) #3
%.pre = load i16, ptr %c, align 2
%.pre3 = sext i16 %.pre to i32
br label %cont
cont:
%conv1.pre-phi = phi i32 [ %.pre3, %handler.add_overflow ], [ %conv, %entry ]
%6 = extractvalue { i32, i1 } %2, 0
store i32 %6, ptr %a, align 4
ret i32 %conv1.pre-phi
}
declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1
declare void @__ubsan_handle_add_overflow(ptr, i64, i64) local_unnamed_addr #2
attributes #0 = { mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #2 = { uwtable }
attributes #3 = { nounwind }
If we mark __ubsan_handle_add_overflow(_abort)
as memory(argmem: read, inaccessiblemem: readwrite)
, we can avoid reloading c
after the call to __ubsan_handle_add_overflow
.
TBH this example doesn't demonstrate a performance issue since we only optimize code in the cold path. However, it would allow more aggressive LICM in the hot path, which improves the performance of fuzzers like AFL.
Metadata
Metadata
Assignees
Labels
clang:codegenIR generation bugs: mangling, exceptions, etc.IR generation bugs: mangling, exceptions, etc.compiler-rt:ubsanUndefined behavior sanitizerUndefined behavior sanitizermissed-optimization