; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s declare float @llvm.ldexp.f32.i32(float, i32) declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>) declare float @llvm.ldexp.f32.i64(float, i64) ; 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:%.*]] = add i32 [[A]], [[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 } ; 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:%.*]] = add i32 [[A]], [[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:%.*]] = add <2 x i32> [[A]], [[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_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:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 32) ; 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_opposite_constants(float %x) { ; CHECK-LABEL: define float @ldexp_ldexp_opposite_constants ; CHECK-SAME: (float [[X:%.*]]) { ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 0) ; 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 -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: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 0) ; 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_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: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 0) ; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], 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 } !0 = !{i32 -127, i32 0} !1 = !{i32 0, i32 127}