When we do simplification via AAPotentialValues or AAValueConstantRange we need to simplify the operands of an instruction we deconstruct first. This does not only improve the result, see for example range.ll, but is required as we allow outside AAs to provide simplification rules via callbacks. If we do ignore the simplification rules and base other simplifications on the IR instead we can create an inconsistent state.
108 lines
3.0 KiB
LLVM
108 lines
3.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=attributor -S < %s | FileCheck %s --check-prefixes=CHECK
|
|
; RUN: opt -passes=attributor -attributor-print-call-graph -S -disable-output < %s | FileCheck %s --check-prefixes=DOT
|
|
|
|
define dso_local void @func1() {
|
|
; CHECK-LABEL: @func1(
|
|
; CHECK-NEXT: br label [[TMP2:%.*]]
|
|
; CHECK: 1:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: 2:
|
|
; CHECK-NEXT: call void @func3()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%1 = icmp ne i32 0, 0
|
|
br i1 %1, label %2, label %3
|
|
|
|
2: ; preds = %0
|
|
call void @func2()
|
|
br label %3
|
|
|
|
3: ; preds = %2, %0
|
|
call void () @func3()
|
|
ret void
|
|
}
|
|
|
|
declare void @func3()
|
|
declare void @func4()
|
|
|
|
define dso_local void @func2() {
|
|
; CHECK-LABEL: @func2(
|
|
; CHECK-NEXT: call void @func4()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @func4()
|
|
ret void
|
|
}
|
|
|
|
|
|
define void @func5(i32 %0) {
|
|
; CHECK-LABEL: @func5(
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
|
|
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], void ()* @func4, void ()* @func3
|
|
; CHECK-NEXT: call void [[TMP3]]()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%2 = icmp ne i32 %0, 0
|
|
%3 = select i1 %2, void ()* @func4, void ()* @func3
|
|
call void () %3()
|
|
ret void
|
|
}
|
|
|
|
define void @broker(void ()* %unknown) !callback !0 {
|
|
; CHECK-LABEL: @broker(
|
|
; CHECK-NEXT: call void [[UNKNOWN:%.*]]()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void %unknown()
|
|
ret void
|
|
}
|
|
|
|
define void @func6() {
|
|
; CHECK-LABEL: @func6(
|
|
; CHECK-NEXT: call void @broker(void ()* nocapture nofree noundef @func3)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @broker(void ()* @func3)
|
|
ret void
|
|
}
|
|
|
|
define void @func7(void ()* %unknown) {
|
|
; CHECK-LABEL: @func7(
|
|
; CHECK-NEXT: call void [[UNKNOWN:%.*]](), !callees !2
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void %unknown(), !callees !2
|
|
ret void
|
|
}
|
|
|
|
!0 = !{!1}
|
|
!1 = !{i64 0, i1 false}
|
|
!2 = !{void ()* @func3, void ()* @func4}
|
|
|
|
; UTC_ARGS: --disable
|
|
|
|
; DOT-DAG: Node[[FUNC1:0x[a-z0-9]+]] [shape=record,label="{func1}"];
|
|
; DOT-DAG: Node[[FUNC2:0x[a-z0-9]+]] [shape=record,label="{func2}"];
|
|
; DOT-DAG: Node[[FUNC3:0x[a-z0-9]+]] [shape=record,label="{func3}"];
|
|
; DOT-DAG: Node[[FUNC4:0x[a-z0-9]+]] [shape=record,label="{func4}"];
|
|
; DOT-DAG: Node[[FUNC5:0x[a-z0-9]+]] [shape=record,label="{func5}"];
|
|
; DOT-DAG: Node[[FUNC6:0x[a-z0-9]+]] [shape=record,label="{func6}"];
|
|
; DOT-DAG: Node[[FUNC7:0x[a-z0-9]+]] [shape=record,label="{func7}"];
|
|
|
|
; DOT-DAG: Node[[BROKER:0x[a-z0-9]+]] [shape=record,label="{broker}"];
|
|
|
|
; DOT-DAG: Node[[FUNC1]] -> Node[[FUNC3]];
|
|
; DOT-DAG: Node[[FUNC2]] -> Node[[FUNC4]];
|
|
; DOT-DAG: Node[[FUNC5]] -> Node[[FUNC3]];
|
|
; DOT-DAG: Node[[FUNC5]] -> Node[[FUNC4]];
|
|
|
|
; DOT-DAG: Node[[FUNC6]] -> Node[[BROKER]];
|
|
|
|
; This one gets added because of the callback metadata.
|
|
; DOT-DAG: Node[[FUNC6]] -> Node[[FUNC3]];
|
|
|
|
; These ones are added because of the callees metadata.
|
|
; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC3]];
|
|
; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC4]];
|