| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 | |
| ; RUN: opt -S -passes=instcombine < %s | FileCheck %s | |
| ; select c, (ldexp val, e0), (ldexp val, e1) -> ldexp val, (select c, e0, e1) | |
| define float @select_ldexp_f32_sameval_differentexp(i1 %cond, float %val, i32 %exp0, i32 %exp1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_selectflags(i1 %cond, float %val, i32 %exp0, i32 %exp1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_selectflags | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| %select = select nnan i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_ldexp_intersect_flags(i1 %cond, float %val, i32 %exp0, i32 %exp1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_ldexp_intersect_flags | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call nnan nsz float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| %ldexp1 = call nnan float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_ldexp_intersect_flags_union_select(i1 %cond, float %val, i32 %exp0, i32 %exp1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_ldexp_intersect_flags_union_select | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call nnan nsz float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| %ldexp1 = call nnan float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| %select = select ninf i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_multiuse0(i1 %cond, float %val, i32 %exp0, i32 %exp1, ptr %ptr) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_multiuse0 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[EXP0]]) | |
| ; CHECK-NEXT: store float [[LDEXP0]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| store float %ldexp0, ptr %ptr | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_multiuse1(i1 %cond, float %val, i32 %exp0, i32 %exp1, ptr %ptr) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_multiuse1 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[EXP1]]) | |
| ; CHECK-NEXT: store float [[LDEXP1]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| store float %ldexp1, ptr %ptr | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_multiuse_both(i1 %cond, float %val, i32 %exp0, i32 %exp1, ptr %ptr0, ptr %ptr1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_multiuse_both | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]], ptr [[PTR0:%.*]], ptr [[PTR1:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[EXP0]]) | |
| ; CHECK-NEXT: store float [[LDEXP0]], ptr [[PTR0]], align 4 | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[EXP1]]) | |
| ; CHECK-NEXT: store float [[LDEXP1]], ptr [[PTR1]], align 4 | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[LDEXP0]], float [[LDEXP1]] | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| store float %ldexp0, ptr %ptr0 | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp1) | |
| store float %ldexp1, ptr %ptr1 | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| ; select c, (ldexp val0, e), (ldexp val1, ee) -> ldexp (select c, val0, val1), e | |
| define float @select_ldexp_f32_differentval_sameexp(i1 %cond, float %val0, float %val1, i32 %exp) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_sameexp | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_sameexp_selectflags(i1 %cond, float %val0, float %val1, i32 %exp) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_sameexp_selectflags | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp) | |
| %select = select nnan i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_sameexp_ldexp_intersect_flags(i1 %cond, float %val0, float %val1, i32 %exp) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_sameexp_ldexp_intersect_flags | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call nnan nsz float @llvm.ldexp.f32.i32(float %val0, i32 %exp) | |
| %ldexp1 = call nnan float @llvm.ldexp.f32.i32(float %val1, i32 %exp) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_sameexp_ldexp_intersect_flags_unino_select(i1 %cond, float %val0, float %val1, i32 %exp) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_sameexp_ldexp_intersect_flags_unino_select | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call nnan nsz float @llvm.ldexp.f32.i32(float %val0, i32 %exp) | |
| %ldexp1 = call nnan float @llvm.ldexp.f32.i32(float %val1, i32 %exp) | |
| %select = select ninf i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_sameexp_multiuse0(i1 %cond, float %val0, float %val1, i32 %exp, ptr %ptr) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_sameexp_multiuse0 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL0]], i32 [[EXP]]) | |
| ; CHECK-NEXT: store float [[LDEXP0]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp) | |
| store float %ldexp0, ptr %ptr | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_sameexp_multiuse1(i1 %cond, float %val0, float %val1, i32 %exp, ptr %ptr) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_sameexp_multiuse1 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: store float [[LDEXP1]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp) | |
| store float %ldexp1, ptr %ptr | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_differentexp(i1 %cond, float %val0, float %val1, i32 %exp0, i32 %exp1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_differentexp | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[TMP2]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp1) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_differentexp_multiuse0(i1 %cond, float %val0, float %val1, i32 %exp0, i32 %exp1, ptr %ptr) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_differentexp_multiuse0 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL0]], i32 [[EXP0]]) | |
| ; CHECK-NEXT: store float [[LDEXP0]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[TMP2]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp0) | |
| store float %ldexp0, ptr %ptr | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp1) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_differentexp_multiuse1(i1 %cond, float %val0, float %val1, i32 %exp0, i32 %exp1, ptr %ptr) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_differentexp_multiuse1 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL1]], i32 [[EXP1]]) | |
| ; CHECK-NEXT: store float [[LDEXP1]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[VAL0]], float [[VAL1]] | |
| ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND]], i32 [[EXP0]], i32 [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[TMP2]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp1) | |
| store float %ldexp1, ptr %ptr | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_differentval_differentexp_multiuse_both(i1 %cond, float %val0, float %val1, i32 %exp0, i32 %exp1, ptr %ptr0, ptr %ptr1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_differentval_differentexp_multiuse_both | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL0:%.*]], float [[VAL1:%.*]], i32 [[EXP0:%.*]], i32 [[EXP1:%.*]], ptr [[PTR0:%.*]], ptr [[PTR1:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL0]], i32 [[EXP0]]) | |
| ; CHECK-NEXT: store float [[LDEXP0]], ptr [[PTR0]], align 4 | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL1]], i32 [[EXP1]]) | |
| ; CHECK-NEXT: store float [[LDEXP1]], ptr [[PTR1]], align 4 | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[LDEXP0]], float [[LDEXP1]] | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val0, i32 %exp0) | |
| store float %ldexp0, ptr %ptr0 | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val1, i32 %exp1) | |
| store float %ldexp1, ptr %ptr1 | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define <2 x float> @select_ldexp_v2f32_sameval_differentexp(<2 x i1> %cond, <2 x float> %val, <2 x i32> %exp0, <2 x i32> %exp1) { | |
| ; CHECK-LABEL: define <2 x float> @select_ldexp_v2f32_sameval_differentexp | |
| ; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[VAL:%.*]], <2 x i32> [[EXP0:%.*]], <2 x i32> [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[EXP0]], <2 x i32> [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[VAL]], <2 x i32> [[TMP1]]) | |
| ; CHECK-NEXT: ret <2 x float> [[SELECT]] | |
| ; | |
| %ldexp0 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %val, <2 x i32> %exp0) | |
| %ldexp1 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %val, <2 x i32> %exp1) | |
| %select = select <2 x i1> %cond, <2 x float> %ldexp0, <2 x float> %ldexp1 | |
| ret <2 x float> %select | |
| } | |
| define <2 x float> @select_ldexp_v2f32_differentval_sameexp(<2 x i1> %cond, <2 x float> %val0, <2 x float> %val1, <2 x i32> %exp) { | |
| ; CHECK-LABEL: define <2 x float> @select_ldexp_v2f32_differentval_sameexp | |
| ; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[VAL0:%.*]], <2 x float> [[VAL1:%.*]], <2 x i32> [[EXP:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[COND]], <2 x float> [[VAL0]], <2 x float> [[VAL1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[TMP1]], <2 x i32> [[EXP]]) | |
| ; CHECK-NEXT: ret <2 x float> [[SELECT]] | |
| ; | |
| %ldexp0 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %val0, <2 x i32> %exp) | |
| %ldexp1 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %val1, <2 x i32> %exp) | |
| %select = select <2 x i1> %cond, <2 x float> %ldexp0, <2 x float> %ldexp1 | |
| ret <2 x float> %select | |
| } | |
| define <2 x float> @select_ldexp_v2f32_differentval_differentexp(<2 x i1> %cond, <2 x float> %val0, <2 x float> %val1, <2 x i32> %exp0, <2 x i32> %exp1) { | |
| ; CHECK-LABEL: define <2 x float> @select_ldexp_v2f32_differentval_differentexp | |
| ; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[VAL0:%.*]], <2 x float> [[VAL1:%.*]], <2 x i32> [[EXP0:%.*]], <2 x i32> [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[COND]], <2 x float> [[VAL0]], <2 x float> [[VAL1]] | |
| ; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[EXP0]], <2 x i32> [[EXP1]] | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[TMP1]], <2 x i32> [[TMP2]]) | |
| ; CHECK-NEXT: ret <2 x float> [[SELECT]] | |
| ; | |
| %ldexp0 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %val0, <2 x i32> %exp0) | |
| %ldexp1 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %val1, <2 x i32> %exp1) | |
| %select = select <2 x i1> %cond, <2 x float> %ldexp0, <2 x float> %ldexp1 | |
| ret <2 x float> %select | |
| } | |
| define float @select_ldexp_f32_same(i1 %cond, float %val, i32 %exp) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_same | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP:%.*]]) { | |
| ; CHECK-NEXT: [[SELECT:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[EXP]]) | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| define float @select_ldexp_f32_sameval_differentexp_types(i1 %cond, float %val, i32 %exp0, i64 %exp1) { | |
| ; CHECK-LABEL: define float @select_ldexp_f32_sameval_differentexp_types | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[VAL:%.*]], i32 [[EXP0:%.*]], i64 [[EXP1:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[VAL]], i32 [[EXP0]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i64(float [[VAL]], i64 [[EXP1]]) | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[LDEXP0]], float [[LDEXP1]] | |
| ; CHECK-NEXT: ret float [[SELECT]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %val, i32 %exp0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i64(float %val, i64 %exp1) | |
| %select = select i1 %cond, float %ldexp0, float %ldexp1 | |
| ret float %select | |
| } | |
| ;--------------------------------------------------------------------- | |
| ; ldexp(ldexp(x, a), b) -> ldexp(x, a + b) | |
| ;--------------------------------------------------------------------- | |
| define float @ldexp_ldexp(float %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_reassoc_ldexp(float %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_ldexp | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_reassoc(float %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_reassoc | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_reassoc_ldexp_reassoc(float %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_ldexp_reassoc | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_reassoc_nsz_ldexp_reassoc_nsz(float %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_nsz_ldexp_reassoc_nsz | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc nsz float @llvm.ldexp.f32.i32(float [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call reassoc nsz float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| ; Test that we or the inner and outer flags | |
| define float @ldexp_reassoc_ldexp_reassoc_preserve_flags(float %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_ldexp_reassoc_preserve_flags | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc nnan ninf float @llvm.ldexp.f32.i32(float [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc ninf float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call reassoc nnan float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define <2 x float> @ldexp_reassoc_ldexp_reassoc_vec(<2 x float> %x, <2 x i32> %a, <2 x i32> %b) { | |
| ; CHECK-LABEL: define <2 x float> @ldexp_reassoc_ldexp_reassoc_vec | |
| ; CHECK-SAME: (<2 x float> [[X:%.*]], <2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> [[A]], <2 x i32> [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> [[TMP1]]) | |
| ; CHECK-NEXT: ret <2 x float> [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> %a) | |
| %ldexp1 = call reassoc <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %ldexp0, <2 x i32> %b) | |
| ret <2 x float> %ldexp1 | |
| } | |
| define float @ldexp_reassoc_ldexp_reassoc_i8_exp_not_safe(float %x, i8 %a, i8 %b) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_ldexp_reassoc_i8_exp_not_safe | |
| ; CHECK-SAME: (float [[X:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call reassoc float @llvm.ldexp.f32.i8(float [[X]], i8 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i8(float [[LDEXP0]], i8 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i8(float %x, i8 %a) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i8(float %ldexp0, i8 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_reassoc_ldexp_reassoc_i64_exp_safe(float %x, i64 %a, i64 %b) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_ldexp_reassoc_i64_exp_safe | |
| ; CHECK-SAME: (float [[X:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[A]], i64 [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i64(float [[X]], i64 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i64(float %x, i64 %a) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i64(float %ldexp0, i64 %b) | |
| ret float %ldexp1 | |
| } | |
| define half @ldexp_reassoc_ldexp_reassoc_f16_i8_exp_safe(half %x, i8 %a, i8 %b) { | |
| ; CHECK-LABEL: define half @ldexp_reassoc_ldexp_reassoc_f16_i8_exp_safe | |
| ; CHECK-SAME: (half [[X:%.*]], i8 [[A:%.*]], i8 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A]], i8 [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc half @llvm.ldexp.f16.i8(half [[X]], i8 [[TMP1]]) | |
| ; CHECK-NEXT: ret half [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc half @llvm.ldexp.f16.i8(half %x, i8 %a) | |
| %ldexp1 = call reassoc half @llvm.ldexp.f16.i8(half %ldexp0, i8 %b) | |
| ret half %ldexp1 | |
| } | |
| define ppc_fp128 @ldexp_reassoc_ldexp_reassoc_ppcf128(ppc_fp128 %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define ppc_fp128 @ldexp_reassoc_ldexp_reassoc_ppcf128 | |
| ; CHECK-SAME: (ppc_fp128 [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret ppc_fp128 [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 %x, i32 %a) | |
| %ldexp1 = call reassoc ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 %ldexp0, i32 %b) | |
| ret ppc_fp128 %ldexp1 | |
| } | |
| define float @ldexp_multi_use_ldexp(float %x, i32 %a, i32 %b, ptr %ptr) { | |
| ; CHECK-LABEL: define float @ldexp_multi_use_ldexp | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: store float [[LDEXP0]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| store float %ldexp0, ptr %ptr | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| ; Test edge case where the intrinsic is declared with different int types. | |
| define float @ldexp_ldexp_different_exp_type(float %x, i32 %a, i64 %b) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_different_exp_type | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i64 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i64(float [[LDEXP0]], i64 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i64(float %ldexp0, i64 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_constants(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_constants | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc float [[X]], f0x4F800000 | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 24) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_constants_nsz(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc nsz float [[X]], f0x4F800000 | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 8) | |
| %ldexp1 = call reassoc nsz float @llvm.ldexp.f32.i32(float %ldexp0, i32 24) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_constants_nsz0(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz0 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc float [[X]], f0x4F800000 | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc nsz float @llvm.ldexp.f32.i32(float %x, i32 8) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 24) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_constants_nsz1(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz1 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = fmul reassoc nsz float [[X]], f0x4F800000 | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8) | |
| %ldexp1 = call reassoc nsz float @llvm.ldexp.f32.i32(float %ldexp0, i32 24) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_opposite_constants(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_opposite_constants | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: ret float [[X]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 -8) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_negated_variable_reassoc(float %x, i32 %a) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_negated_variable_reassoc | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]]) { | |
| ; CHECK-NEXT: [[NEG_A:%.*]] = sub i32 0, [[A]] | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 [[NEG_A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %neg.a = sub i32 0, %a | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 %neg.a) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_intmin_intmin_reassoc(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_intmin_intmin_reassoc | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 -2147483648) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 -2147483648) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 -2147483648) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_negated_variable(float %x, i32 %a) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_negated_variable | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[NEG_A:%.*]] = sub i32 0, [[A]] | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[NEG_A]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %neg.a = sub i32 0, %a | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %neg.a) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_first_exp_known_positive(float %x, i32 %a.arg, i32 %b) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_first_exp_known_positive | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A_ARG:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[A:%.*]] = and i32 [[A_ARG]], 127 | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %a = and i32 %a.arg, 127 | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_first_second_known_positive(float %x, i32 %a, i32 %b.arg) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_first_second_known_positive | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]], i32 [[B_ARG:%.*]]) { | |
| ; CHECK-NEXT: [[B:%.*]] = and i32 [[B_ARG]], 127 | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %b = and i32 %b.arg, 127 | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_both_exp_known_positive(float %x, i32 %a.arg, i32 %b.arg) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_both_exp_known_positive | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[A_ARG:%.*]], i32 [[B_ARG:%.*]]) { | |
| ; CHECK-NEXT: [[A:%.*]] = and i32 [[A_ARG]], 127 | |
| ; CHECK-NEXT: [[B:%.*]] = and i32 [[B_ARG]], 127 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[A]], [[B]] | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %a = and i32 %a.arg, 127 | |
| %b = and i32 %b.arg, 127 | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_both_exp_known_negative(float %x, ptr %a.ptr, ptr %b.ptr) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_both_exp_known_negative | |
| ; CHECK-SAME: (float [[X:%.*]], ptr [[A_PTR:%.*]], ptr [[B_PTR:%.*]]) { | |
| ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4, !range [[RNG0:![0-9]+]] | |
| ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4, !range [[RNG0]] | |
| ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[A]], [[B]] | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[TMP1]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %a = load i32, ptr %a.ptr, !range !0 | |
| %b = load i32, ptr %b.ptr, !range !0 | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_exp_known_negative_and_positive(float %x, ptr %a.ptr, ptr %b.ptr) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_exp_known_negative_and_positive | |
| ; CHECK-SAME: (float [[X:%.*]], ptr [[A_PTR:%.*]], ptr [[B_PTR:%.*]]) { | |
| ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4, !range [[RNG0]] | |
| ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4, !range [[RNG1:![0-9]+]] | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %a = load i32, ptr %a.ptr, !range !0 | |
| %b = load i32, ptr %b.ptr, !range !1 | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_exp_known_positive_and_negative(float %x, ptr %a.ptr, ptr %b.ptr) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_exp_known_positive_and_negative | |
| ; CHECK-SAME: (float [[X:%.*]], ptr [[A_PTR:%.*]], ptr [[B_PTR:%.*]]) { | |
| ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4, !range [[RNG1]] | |
| ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4, !range [[RNG0]] | |
| ; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[A]]) | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[B]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %a = load i32, ptr %a.ptr, !range !1 | |
| %b = load i32, ptr %b.ptr, !range !0 | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 %a) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %b) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_reassoc_ldexp_reassoc_0(float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_reassoc_ldexp_reassoc_0 | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 0) | |
| %ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 %y) | |
| ret float %ldexp1 | |
| } | |
| define float @ldexp_ldexp_0(float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_ldexp_0 | |
| ; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]]) | |
| ; CHECK-NEXT: ret float [[LDEXP1]] | |
| ; | |
| %ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 0) | |
| %ldexp1 = call float @llvm.ldexp.f32.i32(float %ldexp0, i32 %y) | |
| ret float %ldexp1 | |
| } | |
| ;--------------------------------------------------------------------- | |
| ; ldexp(x, k) -> fmul x, 2**k | |
| ;--------------------------------------------------------------------- | |
| define float @ldexp_neg150(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg150 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -150) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -150) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg149(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg149 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 1.401300e-45 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -149) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg148(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg148 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 2.802600e-45 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -148) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg127(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg127 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x00400000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -127) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg126(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg126 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x00800000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -126) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg125(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg125 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x01000000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -125) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg16(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg16 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x37800000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -16) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg8(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg8 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 3.906250e-03 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -8) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg4(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg4 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 6.250000e-02 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -4) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg2(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg2 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 2.500000e-01 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -2) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg1(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg1 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 5.000000e-01 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -1) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_0(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_0 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: ret float [[X]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 0) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_1(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_1 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 2.000000e+00 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 1) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_2(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_2 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 4.000000e+00 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 2) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_3(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_3 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 8.000000e+00 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 3) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_10(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_10 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 1.024000e+03 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 10) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_125(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_125 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x7E000000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 125) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_126(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_126 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x7E800000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 126) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_127(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_127 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], f0x7F000000 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 127) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_128(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_128 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 128) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 128) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_254(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_254 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 254) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 254) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_255(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_255 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 255) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 255) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_256(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_256 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 256) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 256) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg254(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg254 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -254) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -254) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg255(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg255 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -255) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -255) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg256(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg256 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -256) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -256) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_neg260(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_neg260 | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -260) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 -260) | |
| ret float %ldexp | |
| } | |
| define <2 x float> @ldexp_3_vector(<2 x float> %x) { | |
| ; CHECK-LABEL: define <2 x float> @ldexp_3_vector | |
| ; CHECK-SAME: (<2 x float> [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul <2 x float> [[X]], splat (float 8.000000e+00) | |
| ; CHECK-NEXT: ret <2 x float> [[LDEXP]] | |
| ; | |
| %ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 3, i32 3>) | |
| ret <2 x float> %ldexp | |
| } | |
| define <2 x float> @ldexp_3_undef_vector(<2 x float> %x) { | |
| ; CHECK-LABEL: define <2 x float> @ldexp_3_undef_vector | |
| ; CHECK-SAME: (<2 x float> [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> <i32 3, i32 poison>) | |
| ; CHECK-NEXT: ret <2 x float> [[LDEXP]] | |
| ; | |
| %ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 3, i32 poison>) | |
| ret <2 x float> %ldexp | |
| } | |
| define <2 x float> @ldexp_3_4_vector(<2 x float> %x) { | |
| ; CHECK-LABEL: define <2 x float> @ldexp_3_4_vector | |
| ; CHECK-SAME: (<2 x float> [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> <i32 3, i32 4>) | |
| ; CHECK-NEXT: ret <2 x float> [[LDEXP]] | |
| ; | |
| %ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 3, i32 4>) | |
| ret <2 x float> %ldexp | |
| } | |
| define float @ldexp_2_flags(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_2_flags | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul nsz contract float [[X]], 4.000000e+00 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call contract nsz float @llvm.ldexp.f32.i32(float %x, i32 2) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_metadata(float %x) { | |
| ; CHECK-LABEL: define float @ldexp_metadata | |
| ; CHECK-SAME: (float [[X:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul float [[X]], 4.000000e+00 | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 2), !foo !2 | |
| ret float %ldexp | |
| } | |
| define float @ldexp_8_contractable(float %x, float %y) { | |
| ; CHECK-LABEL: define float @ldexp_8_contractable | |
| ; CHECK-SAME: (float [[X:%.*]], float [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = fmul contract float [[X]], 4.000000e+00 | |
| ; CHECK-NEXT: [[FADD:%.*]] = fadd contract float [[LDEXP]], [[Y]] | |
| ; CHECK-NEXT: ret float [[FADD]] | |
| ; | |
| %ldexp = call contract float @llvm.ldexp.f32.i32(float %x, i32 2) | |
| %fadd = fadd contract float %ldexp, %y | |
| ret float %fadd | |
| } | |
| define float @ldexp_f32_mask_select_0(i1 %cond, float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_f32_mask_select_0 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]]) | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = select i1 [[COND]], float [[TMP1]], float [[X]] | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 %y, i32 0 | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_nnan_f32_mask_select_0(i1 %cond, float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_nnan_f32_mask_select_0 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]]) | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = select i1 [[COND]], float [[TMP1]], float [[X]] | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 %y, i32 0 | |
| %ldexp = call nnan float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_flags_f32_mask_select_0(i1 %cond, float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_flags_f32_mask_select_0 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call ninf nsz float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]]) | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = select i1 [[COND]], float [[TMP1]], float [[X]] | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 %y, i32 0 | |
| %ldexp = call nsz ninf float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_f32_mask_select_0_swap(i1 %cond, float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_f32_mask_select_0_swap | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]]) | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = select i1 [[COND]], float [[X]], float [[TMP1]] | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 0, i32 %y | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_f32_mask_select_1(i1 %cond, float %x, i32 %y) { | |
| ; CHECK-LABEL: define float @ldexp_f32_mask_select_1 | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[Y]], i32 1 | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[SELECT]]) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 %y, i32 1 | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_f32_mask_select_0_multi_use(i1 %cond, float %x, i32 %y, ptr %ptr) { | |
| ; CHECK-LABEL: define float @ldexp_f32_mask_select_0_multi_use | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[Y]], i32 0 | |
| ; CHECK-NEXT: store i32 [[SELECT]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[SELECT]]) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 %y, i32 0 | |
| store i32 %select, ptr %ptr | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_f32_mask_select_0_swap_multi_use(i1 %cond, float %x, i32 %y, ptr %ptr) { | |
| ; CHECK-LABEL: define float @ldexp_f32_mask_select_0_swap_multi_use | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]], ptr [[PTR:%.*]]) { | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 0, i32 [[Y]] | |
| ; CHECK-NEXT: store i32 [[SELECT]], ptr [[PTR]], align 4 | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[SELECT]]) | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 0, i32 %y | |
| store i32 %select, ptr %ptr | |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %select) | |
| ret float %ldexp | |
| } | |
| define float @ldexp_f32_mask_select_0_strictfp(i1 %cond, float %x, i32 %y) #0 { | |
| ; CHECK-LABEL: define float @ldexp_f32_mask_select_0_strictfp | |
| ; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR1:[0-9]+]] { | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], i32 [[Y]], i32 0 | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float [[X]], i32 [[SELECT]], metadata !"round.dynamic", metadata !"fpexcept.strict") | |
| ; CHECK-NEXT: ret float [[LDEXP]] | |
| ; | |
| %select = select i1 %cond, i32 %y, i32 0 | |
| %ldexp = call float @llvm.experimental.constrained.ldexp.f32.i32(float %x, i32 %select, metadata !"round.dynamic", metadata !"fpexcept.strict") | |
| ret float %ldexp | |
| } | |
| define <2 x float> @ldexp_v2f32_mask_select_0(<2 x i1> %cond, <2 x float> %x, <2 x i32> %y) { | |
| ; CHECK-LABEL: define <2 x float> @ldexp_v2f32_mask_select_0 | |
| ; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> [[Y]]) | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = select <2 x i1> [[COND]], <2 x float> [[TMP1]], <2 x float> [[X]] | |
| ; CHECK-NEXT: ret <2 x float> [[LDEXP]] | |
| ; | |
| %select = select <2 x i1> %cond, <2 x i32> %y, <2 x i32> zeroinitializer | |
| %ldexp = call nsz nnan <2 x float> @llvm.ldexp.f32.v2i32(<2 x float> %x, <2 x i32> %select) | |
| ret <2 x float> %ldexp | |
| } | |
| define <2 x float> @ldexp_v2f32_mask_select_0_swap(<2 x i1> %cond, <2 x float> %x, <2 x i32> %y) { | |
| ; CHECK-LABEL: define <2 x float> @ldexp_v2f32_mask_select_0_swap | |
| ; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> [[Y]]) | |
| ; CHECK-NEXT: [[LDEXP:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> [[TMP1]] | |
| ; CHECK-NEXT: ret <2 x float> [[LDEXP]] | |
| ; | |
| %select = select <2 x i1> %cond, <2 x i32> zeroinitializer, <2 x i32> %y | |
| %ldexp = call nsz nnan <2 x float> @llvm.ldexp.f32.v2i32(<2 x float> %x, <2 x i32> %select) | |
| ret <2 x float> %ldexp | |
| } | |
| ; Exponent constants that exceed `int` saturate to +/-inf / +/-0 rather than | |
| ; silently narrowing. | |
| define double @ldexp_i64_exp_above_int_max() { | |
| ; CHECK-LABEL: define double @ldexp_i64_exp_above_int_max() { | |
| ; CHECK-NEXT: ret double +inf | |
| ; | |
| %r = call double @llvm.ldexp.f64.i64(double 1.0, i64 4294967330) | |
| ret double %r | |
| } | |
| define double @ldexp_i64_exp_below_int_min() { | |
| ; CHECK-LABEL: define double @ldexp_i64_exp_below_int_min() { | |
| ; CHECK-NEXT: ret double 0.000000e+00 | |
| ; | |
| %r = call double @llvm.ldexp.f64.i64(double 1.0, i64 -4294967330) | |
| ret double %r | |
| } | |
| define double @ldexp_i64_neg_input_exp_above_int_max() { | |
| ; CHECK-LABEL: define double @ldexp_i64_neg_input_exp_above_int_max() { | |
| ; CHECK-NEXT: ret double -inf | |
| ; | |
| %r = call double @llvm.ldexp.f64.i64(double -1.0, i64 4294967330) | |
| ret double %r | |
| } | |
| define double @ldexp_i64_neg_input_exp_above_int64_max() { | |
| ; CHECK-LABEL: define double @ldexp_i64_neg_input_exp_above_int64_max() { | |
| ; CHECK-NEXT: ret double -inf | |
| ; | |
| ; This constant is 2^65, i.e. it exceeds the range of i64. | |
| %r = call double @llvm.ldexp.f64.i128(double -1.0, i128 36893488147419103232) | |
| ret double %r | |
| } | |
| define double @ldexp_i16_exp_narrow_int() { | |
| ; CHECK-LABEL: define double @ldexp_i16_exp_narrow_int() { | |
| ; CHECK-NEXT: ret double 4.096000e+03 | |
| ; | |
| %r = call double @llvm.ldexp.f64.i16(double 1.0, i16 12) | |
| ret double %r | |
| } | |
| define double @ldexp_i16_exp_narrow_int_negative() { | |
| ; CHECK-LABEL: define double @ldexp_i16_exp_narrow_int_negative() { | |
| ; CHECK-NEXT: ret double 4.000000e+00 | |
| ; | |
| %r = call double @llvm.ldexp.f64.i16(double 8.0, i16 -1) | |
| ret double %r | |
| } | |
| attributes #0 = { strictfp } | |
| !0 = !{i32 -127, i32 0} | |
| !1 = !{i32 0, i32 127} | |
| !2 = !{} |