Skip to content

Commit f7ef7ea

Browse files
committed
llvm-reduce: Fix assert if call type mismatches function type
This fixes asserting on IR with undefined behavior from calls with a type that does not match the type of the target function. Just ignore callsites which already didn't match the function signature. This is the most straightforward fix, the reference to the global will be replaced later anyway. A better implementation would try to pad out unused arguments, particularly in the cases where the signatures only differ in type and not count. Fixes #69312, fixes #100880
1 parent 8249492 commit f7ef7ea

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-reduce %s -o %t --abort-on-invalid-reduction --delta-passes=operands-to-args --test FileCheck --test-arg %s --test-arg --check-prefix=INTERESTING --test-arg --input-file
2+
; RUN: FileCheck %s --input-file %t --check-prefix=REDUCED
3+
4+
@a = dso_local global i8 0, align 1
5+
@b = dso_local global i16 0, align 2
6+
7+
; INTERESTING-LABEL: define void @c(
8+
; INTERESTING: sext
9+
; INTERESTING: icmp
10+
11+
; REDUCED: define void @c(ptr %a, i8 %ld0, ptr %b, i16 %ld1, i32 %conv, i32 %conv1, i1 %cmp, i32 %conv2)
12+
; REDUCED: call void @c(i32 noundef signext %conv2)
13+
define void @c() {
14+
entry:
15+
%ld0 = load i8, ptr @a, align 1
16+
%conv = zext i8 %ld0 to i32
17+
%ld1 = load i16, ptr @b, align 2
18+
%conv1 = sext i16 %ld1 to i32
19+
%cmp = icmp sge i32 %conv, %conv1
20+
%conv2 = zext i1 %cmp to i32
21+
call void @c(i32 noundef signext %conv2)
22+
ret void
23+
}
24+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; RUN: llvm-reduce %s -o %t --abort-on-invalid-reduction --delta-passes=operands-to-args --test FileCheck --test-arg %s --test-arg --match-full-lines --test-arg --check-prefix=INTERESTING --test-arg --input-file
2+
; RUN: FileCheck %s --input-file %t --check-prefixes=REDUCED,INTERESTING
3+
4+
; REDUCED-LABEL: define void @func(i32 %k, i32 %extra.arg, ptr %Global, ptr %Local) {
5+
6+
; Keep one reference to the original value.
7+
; INTERESTING: %[[LOCAL:Local[0-9]*]] = alloca i32, align 4
8+
9+
; Everything else must use the function argument.
10+
; REDUCED: store i32 21, ptr %Global, align 4
11+
; REDUCED: store i32 0, ptr %Local, align 4
12+
; REDUCED: store i32 0, ptr %Global, align 4
13+
14+
; Do not add any arguments for %Keep and @GlobalKeep.
15+
; INTERESTING: %[[KEEP:LocalKeep[0-9]*]] = add i32 %k, 21
16+
; INTERESTING: store i32 %[[KEEP]], ptr @GlobalKeep, align 4
17+
18+
; Do not add any arguments if the call type was already mismatched
19+
20+
; INTERESTING-LABEL: define void @mismatched_func_caller() {
21+
; REDUCED: call void @func(i32 21)
22+
23+
@Global = global i32 42
24+
@GlobalKeep = global i32 42
25+
26+
define void @func(i32 %k, i32 %extra.arg) {
27+
entry:
28+
%Local = alloca i32, align 4
29+
store i32 21, ptr @Global, align 4
30+
store i32 0, ptr %Local, align 4
31+
store i32 0, ptr @Global, align 4
32+
%LocalKeep = add i32 %k, 21
33+
store i32 %LocalKeep, ptr @GlobalKeep, align 4
34+
ret void
35+
}
36+
37+
; This call has the wrong signature for the original underlying call,
38+
; so getCalledFunction does not return a reference to the function.
39+
define void @mismatched_func_caller() {
40+
entry:
41+
call void @func(i32 21)
42+
ret void
43+
}
44+

llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,20 @@ static void replaceFunctionCalls(Function *OldF, Function *NewF) {
6161
for (Use &U : OldF->uses()) {
6262
auto *CI = cast<CallBase>(U.getUser());
6363
assert(&U == &CI->getCalledOperandUse());
64-
assert(CI->getCalledFunction() == OldF);
65-
Callers.push_back(CI);
64+
65+
Function *CalledF = CI->getCalledFunction();
66+
if (CalledF == OldF) {
67+
Callers.push_back(CI);
68+
} else {
69+
// The call may have undefined behavior by calling a function with a
70+
// mismatched signature. In this case, do not bother adjusting the
71+
// callsites to pad with any new arguments.
72+
73+
// TODO: Better QoI to try to add new arguments to the end, and ignore
74+
// existing mismatches.
75+
assert(!CalledF && CI->getCalledOperand()->stripPointerCasts() == OldF &&
76+
"only expected call and function signature mismatch");
77+
}
6678
}
6779

6880
// Call arguments for NewF.

0 commit comments

Comments
 (0)