| ; 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 |
| } |
| |
| 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:%.*]] = add i32 [[A]], [[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:%.*]] = 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_constants_nsz(float %x) { |
| ; CHECK-LABEL: define float @ldexp_ldexp_constants_nsz |
| ; CHECK-SAME: (float [[X:%.*]]) { |
| ; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc nsz float @llvm.ldexp.f32.i32(float [[X]], i32 32) |
| ; 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:%.*]] = call reassoc nsz float @llvm.ldexp.f32.i32(float [[X]], i32 32) |
| ; 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:%.*]] = call reassoc nsz 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 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: ret float [[X]] |
| ; |
| %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: [[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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -149) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -148) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -127) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -126) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -125) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -16) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -8) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -4) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -2) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 -1) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 1) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 2) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 3) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 10) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 125) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 126) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 127) |
| ; CHECK-NEXT: ret float [[LDEXP]] |
| ; |
| %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 127) |
| 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:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> <i32 3, i32 3>) |
| ; 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:%.*]] = call nsz contract float @llvm.ldexp.f32.i32(float [[X]], i32 2) |
| ; 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:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 2), !foo !2 |
| ; 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:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[X]], i32 2) |
| ; 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 |
| } |
| |
| !0 = !{i32 -127, i32 0} |
| !1 = !{i32 0, i32 127} |
| !2 = !{} |