
If x is NaN, then fmul (x, 1) may produce a different NaN value. Our float semantics explicitly permit folding fmul (x, 1) to x, but we can't do this when we're replacing a select input, as selects are supposed to preserve the exact bitwise value. Fixes https://github.com/llvm/llvm-project/pull/115152#issuecomment-2545773114.
257 lines
8.5 KiB
LLVM
257 lines
8.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
|
|
|
|
define float @select_fcmp_fsub_oeq(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_oeq(
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 2.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fadd, float 0.0
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_oeq_zero(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_oeq_zero(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 2.000000e+00
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp oeq float %x, 0.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fadd, float 2.0
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_ueq(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_ueq(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp ueq float [[X:%.*]], 2.000000e+00
|
|
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[FADD]], float 0.000000e+00
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp ueq float %x, 2.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fadd, float 0.0
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_ueq_nnan(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_ueq_nnan(
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%fcmp = fcmp nnan ueq float %x, 2.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fadd, float 0.0
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_une(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_une(
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%fcmp = fcmp une float %x, 2.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float 0.0, float %fadd
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_une_zero(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_une_zero(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float 2.000000e+00, float [[FADD]]
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp une float %x, 0.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float 2.0, float %fadd
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_one(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_one(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp one float [[X:%.*]], 2.000000e+00
|
|
; CHECK-NEXT: [[FADD:%.*]] = fsub float [[X]], 2.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float 0.000000e+00, float [[FADD]]
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp one float %x, 2.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float 0.0, float %fadd
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fsub_one_nnan(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fsub_one_nnan(
|
|
; CHECK-NEXT: ret float 0.000000e+00
|
|
;
|
|
%fcmp = fcmp nnan one float %x, 2.0
|
|
%fadd = fsub float %x, 2.0
|
|
%sel = select i1 %fcmp, float 0.0, float %fadd
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fadd(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fadd(
|
|
; CHECK-NEXT: ret float 4.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 2.0
|
|
%fadd = fadd float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fadd, float 4.0
|
|
ret float %sel
|
|
}
|
|
|
|
define <2 x float> @select_fcmp_fadd_vec(<2 x float> %x) {
|
|
; CHECK-LABEL: @select_fcmp_fadd_vec(
|
|
; CHECK-NEXT: ret <2 x float> splat (float 4.000000e+00)
|
|
;
|
|
%fcmp = fcmp oeq <2 x float> %x, <float 2.0, float 2.0>
|
|
%fadd = fadd <2 x float> %x, <float 2.0, float 2.0>
|
|
%sel = select <2 x i1> %fcmp, <2 x float> %fadd, <2 x float> <float 4.0, float 4.0>
|
|
ret <2 x float> %sel
|
|
}
|
|
|
|
|
|
; Should not fold, because the fmul by identity may produce a different NaN
|
|
; value.
|
|
define float @select_fcmp_fmul_nonrefinement(float %x, float %y) {
|
|
; CHECK-LABEL: @select_fcmp_fmul_nonrefinement(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
|
|
; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[Y:%.*]], [[X]]
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FMUL]]
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp oeq float %x, 1.0
|
|
%fmul = fmul float %y, %x
|
|
%sel = select i1 %fcmp, float %y, float %fmul
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fmul(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fmul(
|
|
; CHECK-NEXT: ret float 4.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 2.0
|
|
%fmul = fmul float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fmul, float 4.0
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fdiv_nonrefinement(float %x, float %y) {
|
|
; CHECK-LABEL: @select_fcmp_fdiv_nonrefinement(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
|
|
; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[Y:%.*]], [[X]]
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float [[Y]], float [[FDIV]]
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp oeq float %x, 1.0
|
|
%fdiv = fdiv float %y, %x
|
|
%sel = select i1 %fcmp, float %y, float %fdiv
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_fdiv(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_fdiv(
|
|
; CHECK-NEXT: ret float 1.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 2.0
|
|
%fdiv = fdiv float %x, 2.0
|
|
%sel = select i1 %fcmp, float %fdiv, float 1.0
|
|
ret float %sel
|
|
}
|
|
|
|
define float @select_fcmp_frem(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_frem(
|
|
; CHECK-NEXT: ret float 1.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 3.0
|
|
%frem = frem float %x, 2.0
|
|
%sel = select i1 %fcmp, float %frem, float 1.0
|
|
ret float %sel
|
|
}
|
|
|
|
define <2 x float> @select_fcmp_insertelement(<2 x float> %x) {
|
|
; CHECK-LABEL: @select_fcmp_insertelement(
|
|
; CHECK-NEXT: ret <2 x float> <float 4.000000e+00, float 2.000000e+00>
|
|
;
|
|
%fcmp = fcmp oeq <2 x float> %x, <float 2.0, float 2.0>
|
|
%insert = insertelement <2 x float> %x, float 4.0, i64 0
|
|
%sel = select <2 x i1> %fcmp, <2 x float> %insert, <2 x float> <float 4.0, float 2.0>
|
|
ret <2 x float> %sel
|
|
}
|
|
|
|
define <4 x float> @select_fcmp_shufflevector_select(<4 x float> %x) {
|
|
; CHECK-LABEL: @select_fcmp_shufflevector_select(
|
|
; CHECK-NEXT: ret <4 x float> <float poison, float 2.000000e+00, float poison, float 2.000000e+00>
|
|
;
|
|
%fcmp = fcmp oeq <4 x float> %x, <float 2.0, float 2.0, float 2.0, float 2.0>
|
|
%shuffle = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> <i32 4, i32 1, i32 6, i32 3>
|
|
%sel = select <4 x i1> %fcmp, <4 x float> %shuffle, <4 x float> <float poison, float 2.0, float poison, float 2.0>
|
|
ret <4 x float> %sel
|
|
}
|
|
|
|
; The hexfloat constant is PI / 2.
|
|
define float @select_fcmp_sin_nonrefinement(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_sin_nonrefinement(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 0x3FF921FB60000000
|
|
; CHECK-NEXT: [[SIN:%.*]] = call float @llvm.sin.f32(float [[X]])
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float 1.000000e+00, float [[SIN]]
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp oeq float %x, 0x3FF921FB60000000
|
|
%sin = call float @llvm.sin.f32(float %x)
|
|
%sel = select i1 %fcmp, float 1.0, float %sin
|
|
ret float %sel
|
|
}
|
|
|
|
; The hexfloat constant is PI / 2.
|
|
define float @select_fcmp_sin(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_sin(
|
|
; CHECK-NEXT: ret float 1.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 0x3FF921FB60000000
|
|
%sin = call float @llvm.sin.f32(float %x)
|
|
%sel = select i1 %fcmp, float %sin, float 1.0
|
|
ret float %sel
|
|
}
|
|
|
|
; The hexfloat constant is PI.
|
|
define float @select_fcmp_cos_nonrefinement(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_cos_nonrefinement(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 0x400921FB60000000
|
|
; CHECK-NEXT: [[COS:%.*]] = call float @llvm.cos.f32(float [[X]])
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], float -1.000000e+00, float [[COS]]
|
|
; CHECK-NEXT: ret float [[SEL]]
|
|
;
|
|
%fcmp = fcmp oeq float %x, 0x400921FB60000000
|
|
%cos = call float @llvm.cos.f32(float %x)
|
|
%sel = select i1 %fcmp, float -1.0, float %cos
|
|
ret float %sel
|
|
}
|
|
|
|
; The hexfloat constant is PI.
|
|
define float @select_fcmp_cos(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_cos(
|
|
; CHECK-NEXT: ret float -1.000000e+00
|
|
;
|
|
%fcmp = fcmp oeq float %x, 0x400921FB60000000
|
|
%cos = call float @llvm.cos.f32(float %x)
|
|
%sel = select i1 %fcmp, float %cos, float -1.0
|
|
ret float %sel
|
|
}
|
|
|
|
define i32 @select_fcmp_lrint(float %x) {
|
|
; CHECK-LABEL: @select_fcmp_lrint(
|
|
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00
|
|
; CHECK-NEXT: [[LRINT:%.*]] = call i32 @llvm.lrint.i32.f32(float [[X]])
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[FCMP]], i32 [[LRINT]], i32 1
|
|
; CHECK-NEXT: ret i32 [[SEL]]
|
|
;
|
|
%fcmp = fcmp oeq float %x, 1.0
|
|
%lrint = call i32 @llvm.lrint.i32.f32(float %x)
|
|
%sel = select i1 %fcmp, i32 %lrint, i32 1
|
|
ret i32 %sel
|
|
}
|