Unlike every other analysis and transform, simplifyInstruction permitted operating on instructions which are not inserted into a function. This created an edge case no other code needs to really worry about, and limited transforms in cases that can make use of the context function. Only the inliner and a handful of other utilities were making use of this, so just fix up these edge cases. Results in some IR ordering differences since cloned blocks are inserted eagerly now. Plus some additional simplifications trigger (e.g. some add 0s now folded out that previously didn't).
170 lines
6.6 KiB
LLVM
170 lines
6.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt < %s -passes=inline -inline-threshold=20 -S | FileCheck %s
|
|
; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S | FileCheck %s
|
|
|
|
; Make sure there are no crashes when calling computeKnownFPClass with
|
|
; un-inserted cloned instructions.
|
|
|
|
; Hit computeKnownFPClass in a context where the denormal mode is
|
|
; queried for the function for an operand not in a parent function.
|
|
|
|
define i1 @simplify_fcmp_ord_fsub_caller(double nofpclass(zero nan) %i0, double nofpclass(zero nan) %i1) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_fsub_caller
|
|
; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]], double nofpclass(nan zero) [[I1:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fsub double [[I0]], [[I1]]
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
|
|
; CHECK-NEXT: ret i1 [[CMP_I]]
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_fsub_callee(double %i0, double %i1)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_fsub_callee(double %a, double %b) {
|
|
%sub.double.sub = fsub double %a, %b
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @simplify_fcmp_ord_fdiv_caller(double nofpclass(zero nan inf) %i0, double nofpclass(zero nan inf) %i1) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_fdiv_caller
|
|
; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fdiv double [[I0]], [[I1]]
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_fdiv_callee(double %i0, double %i1)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_fdiv_callee(double %a, double %b) {
|
|
%sub.double.sub = fdiv double %a, %b
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @simplify_fcmp_ord_frem_caller(double nofpclass(zero nan inf) %i0, double nofpclass(zero nan inf) %i1) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_frem_caller
|
|
; CHECK-SAME: (double nofpclass(nan inf zero) [[I0:%.*]], double nofpclass(nan inf zero) [[I1:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = frem double [[I0]], [[I1]]
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_frem_callee(double %i0, double %i1)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_frem_callee(double %a, double %b) {
|
|
%sub.double.sub = frem double %a, %b
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @simplify_fcmp_ord_fmul_caller(double nofpclass(zero nan) %i0, double nofpclass(zero nan) %i1) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_fmul_caller
|
|
; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]], double nofpclass(nan zero) [[I1:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = fmul double [[I0]], [[I1]]
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_fmul_callee(double %i0, double %i1)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_fmul_callee(double %a, double %b) {
|
|
%sub.double.sub = fmul double %a, %b
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @simplify_fcmp_ord_sqrt_caller(double nofpclass(zero nan) %i0) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_sqrt_caller
|
|
; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = call double @llvm.sqrt.f64(double [[I0]])
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
|
|
; CHECK-NEXT: ret i1 [[CMP_I]]
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_sqrt_callee(double %i0)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_sqrt_callee(double %a) {
|
|
%sub.double.sub = call double @llvm.sqrt.f64(double %a)
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
declare double @llvm.sqrt.f64(double)
|
|
|
|
define i1 @simplify_fcmp_ord_canonicalize_caller(double nofpclass(zero nan) %i0) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_canonicalize_caller
|
|
; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = call double @llvm.canonicalize.f64(double [[I0]])
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_canonicalize_callee(double %i0)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_canonicalize_callee(double %a) {
|
|
%sub.double.sub = call double @llvm.canonicalize.f64(double %a)
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
declare double @llvm.canonicalize.f64(double)
|
|
|
|
define i1 @simplify_fcmp_ord_log_caller(double nofpclass(zero nan) %i0) {
|
|
; CHECK-LABEL: define i1 @simplify_fcmp_ord_log_caller
|
|
; CHECK-SAME: (double nofpclass(nan zero) [[I0:%.*]]) {
|
|
; CHECK-NEXT: [[SUB_DOUBLE_SUB_I:%.*]] = call double @llvm.log.f64(double [[I0]])
|
|
; CHECK-NEXT: [[CMP_I:%.*]] = fcmp ord double [[SUB_DOUBLE_SUB_I]], 0.000000e+00
|
|
; CHECK-NEXT: ret i1 [[CMP_I]]
|
|
;
|
|
%call = call i1 @simplify_fcmp_ord_log_callee(double %i0)
|
|
ret i1 %call
|
|
}
|
|
|
|
; Make sure we hit the denormal query in isKnownNeverLogicalZero
|
|
define internal i1 @simplify_fcmp_ord_log_callee(double %a) {
|
|
%sub.double.sub = call double @llvm.log.f64(double %a)
|
|
%cmp = fcmp ord double %sub.double.sub, 0.0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
declare double @llvm.log.f64(double)
|
|
|
|
declare float @llvm.maxnum.f32(float, float) #0
|
|
declare <4 x float> @foo() #1
|
|
|
|
define void @caller_maxnum() {
|
|
; CHECK-LABEL: define void @caller_maxnum() {
|
|
; CHECK-NEXT: bb:
|
|
; CHECK-NEXT: [[I1_I:%.*]] = call <4 x float> @foo()
|
|
; CHECK-NEXT: [[I2_I:%.*]] = extractelement <4 x float> [[I1_I]], i64 0
|
|
; CHECK-NEXT: [[I3_I:%.*]] = fmul float [[I2_I]], 0.000000e+00
|
|
; CHECK-NEXT: [[I4_I:%.*]] = call float @llvm.maxnum.f32(float [[I3_I]], float 0.000000e+00)
|
|
; CHECK-NEXT: [[I5_I:%.*]] = call float @llvm.maxnum.f32(float [[I4_I]], float [[I2_I]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
bb:
|
|
call void @callee_maxnum()
|
|
ret void
|
|
}
|
|
|
|
define internal void @callee_maxnum() {
|
|
bb:
|
|
%i1 = call <4 x float> @foo()
|
|
%i2 = extractelement <4 x float> %i1, i64 0
|
|
%i3 = fmul float %i2, 0.000000e+00
|
|
%i4 = call float @llvm.maxnum.f32(float %i3, float 0.000000e+00)
|
|
%i5 = call float @llvm.maxnum.f32(float %i4, float %i2)
|
|
%i6 = fcmp olt float %i5, 0.000000e+00
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
|
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(none) }
|