Files
clang-p2996/llvm/test/Transforms/InstCombine/exp2-1.ll
Martin Storsjö 5a100551d5 [Analysis] Treat ldexpf() as missing on MinGW (#84748)
The function does exist, but it is a plain wrapper over regular ldexp(),
so there's no benefit in calling it over regular ldexp(). Therefore,
treat it as missing.

This fixes builds of Wine for aarch64 with Clang in mingw mode, which
regressed recently in 8d976c7f20. That
commit unlocked transforming calls to ldexp into ldexpf, for some
codepaths within Wine. Wine can use compilers in mingw mode without
the regular mingw runtime libraries, which caused this to fail.
(However, if the transformation to use ldexpf() would have made sense,
the right fix would have been for Wine to provide a similar
ldexpf->ldexp wrapper just like mingw does.)
2024-03-12 12:32:48 +02:00

333 lines
13 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Test that the exp2 library call simplifier works correctly.
;
; RUN: opt < %s -passes=instcombine -S -mtriple=unknown | FileCheck %s -check-prefixes=LDEXP32
; RUN: opt < %s -passes=instcombine -S -mtriple=msp430 | FileCheck %s -check-prefixes=LDEXP16
; RUN: opt < %s -passes=instcombine -S -mtriple=i386-pc-win32 | FileCheck %s -check-prefixes=NOLDEXPF
; RUN: opt < %s -passes=instcombine -S -mtriple=i386-windows-gnu | FileCheck %s -check-prefixes=NOLDEXPF
; RUN: opt < %s -passes=instcombine -S -mtriple=amdgcn-unknown-unknown | FileCheck %s -check-prefixes=NOLDEXP
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
declare double @exp2(double)
declare float @exp2f(float)
declare double @llvm.exp2.f64(double)
declare float @llvm.exp2.f32(float)
declare <2 x float> @llvm.exp2.v2f32(<2 x float>)
; Check exp2(sitofp(x)) -> ldexp(1.0, sext(x)).
define double @test_simplify1(i32 %x) {
; LDEXP32-LABEL: @test_simplify1(
; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]])
; LDEXP32-NEXT: ret double [[LDEXP]]
;
; LDEXP16-LABEL: @test_simplify1(
; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to double
; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; LDEXP16-NEXT: ret double [[RET]]
;
; NOLDEXPF-LABEL: @test_simplify1(
; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[X:%.*]])
; NOLDEXPF-NEXT: ret double [[LDEXP]]
;
; NOLDEXP-LABEL: @test_simplify1(
; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = sitofp i32 %x to double
%ret = call double @exp2(double %conv)
ret double %ret
}
define double @test_simplify2(i16 signext %x) {
; LDEXP32-LABEL: @test_simplify2(
; LDEXP32-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret double [[LDEXP]]
;
; LDEXP16-LABEL: @test_simplify2(
; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[X:%.*]])
; LDEXP16-NEXT: ret double [[LDEXP]]
;
; NOLDEXPF-LABEL: @test_simplify2(
; NOLDEXPF-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32
; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; NOLDEXPF-NEXT: ret double [[LDEXP]]
;
; NOLDEXP-LABEL: @test_simplify2(
; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i16 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = sitofp i16 %x to double
%ret = call double @exp2(double %conv)
ret double %ret
}
define double @test_simplify3(i8 signext %x) {
; LDEXP32-LABEL: @test_simplify3(
; LDEXP32-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret double [[LDEXP]]
;
; LDEXP16-LABEL: @test_simplify3(
; LDEXP16-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16
; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]])
; LDEXP16-NEXT: ret double [[LDEXP]]
;
; NOLDEXPF-LABEL: @test_simplify3(
; NOLDEXPF-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32
; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; NOLDEXPF-NEXT: ret double [[LDEXP]]
;
; NOLDEXP-LABEL: @test_simplify3(
; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i8 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = sitofp i8 %x to double
%ret = call double @exp2(double %conv)
ret double %ret
}
define float @test_simplify4(i32 %x) {
; LDEXP32-LABEL: @test_simplify4(
; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]])
; LDEXP32-NEXT: ret float [[LDEXPF]]
;
; LDEXP16-LABEL: @test_simplify4(
; LDEXP16-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float
; LDEXP16-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]])
; LDEXP16-NEXT: ret float [[RET]]
;
; NOLDEXPF-LABEL: @test_simplify4(
; NOLDEXPF-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float
; NOLDEXPF-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]])
; NOLDEXPF-NEXT: ret float [[RET]]
;
; NOLDEXP-LABEL: @test_simplify4(
; NOLDEXP-NEXT: [[CONV:%.*]] = sitofp i32 [[X:%.*]] to float
; NOLDEXP-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]])
; NOLDEXP-NEXT: ret float [[RET]]
;
%conv = sitofp i32 %x to float
%ret = call float @exp2f(float %conv)
ret float %ret
}
; Check exp2(uitofp(x)) -> ldexp(1.0, zext(x)).
define double @test_no_simplify1(i32 %x) {
; LDEXP32-LABEL: @test_no_simplify1(
; LDEXP32-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double
; LDEXP32-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; LDEXP32-NEXT: ret double [[RET]]
;
; LDEXP16-LABEL: @test_no_simplify1(
; LDEXP16-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double
; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; LDEXP16-NEXT: ret double [[RET]]
;
; NOLDEXPF-LABEL: @test_no_simplify1(
; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double
; NOLDEXPF-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXPF-NEXT: ret double [[RET]]
;
; NOLDEXP-LABEL: @test_no_simplify1(
; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i32 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = uitofp i32 %x to double
%ret = call double @exp2(double %conv)
ret double %ret
}
define double @test_simplify6(i16 zeroext %x) {
; LDEXP32-LABEL: @test_simplify6(
; LDEXP32-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret double [[LDEXP]]
;
; LDEXP16-LABEL: @test_simplify6(
; LDEXP16-NEXT: [[CONV:%.*]] = uitofp i16 [[X:%.*]] to double
; LDEXP16-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; LDEXP16-NEXT: ret double [[RET]]
;
; NOLDEXPF-LABEL: @test_simplify6(
; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32
; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; NOLDEXPF-NEXT: ret double [[LDEXP]]
;
; NOLDEXP-LABEL: @test_simplify6(
; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i16 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = uitofp i16 %x to double
%ret = call double @exp2(double %conv)
ret double %ret
}
define double @test_simplify7(i8 zeroext %x) {
; LDEXP32-LABEL: @test_simplify7(
; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret double [[LDEXP]]
;
; LDEXP16-LABEL: @test_simplify7(
; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16
; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]])
; LDEXP16-NEXT: ret double [[LDEXP]]
;
; NOLDEXPF-LABEL: @test_simplify7(
; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; NOLDEXPF-NEXT: ret double [[LDEXP]]
;
; NOLDEXP-LABEL: @test_simplify7(
; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @exp2(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = uitofp i8 %x to double
%ret = call double @exp2(double %conv)
ret double %ret
}
define float @test_simplify8(i8 zeroext %x) {
; LDEXP32-LABEL: @test_simplify8(
; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret float [[LDEXPF]]
;
; LDEXP16-LABEL: @test_simplify8(
; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16
; LDEXP16-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i16 [[TMP1]])
; LDEXP16-NEXT: ret float [[LDEXPF]]
;
; NOLDEXPF-LABEL: @test_simplify8(
; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float
; NOLDEXPF-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]])
; NOLDEXPF-NEXT: ret float [[RET]]
;
; NOLDEXP-LABEL: @test_simplify8(
; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float
; NOLDEXP-NEXT: [[RET:%.*]] = call float @exp2f(float [[CONV]])
; NOLDEXP-NEXT: ret float [[RET]]
;
%conv = uitofp i8 %x to float
%ret = call float @exp2f(float %conv)
ret float %ret
}
define double @test_simplify9(i8 zeroext %x) {
; LDEXP32-LABEL: @test_simplify9(
; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret double [[LDEXP]]
;
; LDEXP16-LABEL: @test_simplify9(
; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16
; LDEXP16-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i16 [[TMP1]])
; LDEXP16-NEXT: ret double [[LDEXP]]
;
; NOLDEXPF-LABEL: @test_simplify9(
; NOLDEXPF-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
; NOLDEXPF-NEXT: [[LDEXP:%.*]] = call double @ldexp(double 1.000000e+00, i32 [[TMP1]])
; NOLDEXPF-NEXT: ret double [[LDEXP]]
;
; NOLDEXP-LABEL: @test_simplify9(
; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to double
; NOLDEXP-NEXT: [[RET:%.*]] = call double @llvm.exp2.f64(double [[CONV]])
; NOLDEXP-NEXT: ret double [[RET]]
;
%conv = uitofp i8 %x to double
%ret = call double @llvm.exp2.f64(double %conv)
ret double %ret
}
define float @test_simplify10(i8 zeroext %x) {
; LDEXP32-LABEL: @test_simplify10(
; LDEXP32-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret float [[LDEXPF]]
;
; LDEXP16-LABEL: @test_simplify10(
; LDEXP16-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16
; LDEXP16-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i16 [[TMP1]])
; LDEXP16-NEXT: ret float [[LDEXPF]]
;
; NOLDEXPF-LABEL: @test_simplify10(
; NOLDEXPF-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float
; NOLDEXPF-NEXT: [[RET:%.*]] = call float @llvm.exp2.f32(float [[CONV]])
; NOLDEXPF-NEXT: ret float [[RET]]
;
; NOLDEXP-LABEL: @test_simplify10(
; NOLDEXP-NEXT: [[CONV:%.*]] = uitofp i8 [[X:%.*]] to float
; NOLDEXP-NEXT: [[RET:%.*]] = call float @llvm.exp2.f32(float [[CONV]])
; NOLDEXP-NEXT: ret float [[RET]]
;
%conv = uitofp i8 %x to float
%ret = call float @llvm.exp2.f32(float %conv)
ret float %ret
}
define float @sitofp_scalar_intrinsic_with_FMF(i8 %x) {
; LDEXP32-LABEL: @sitofp_scalar_intrinsic_with_FMF(
; LDEXP32-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32
; LDEXP32-NEXT: [[LDEXPF:%.*]] = tail call nnan float @ldexpf(float 1.000000e+00, i32 [[TMP1]])
; LDEXP32-NEXT: ret float [[LDEXPF]]
;
; LDEXP16-LABEL: @sitofp_scalar_intrinsic_with_FMF(
; LDEXP16-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16
; LDEXP16-NEXT: [[LDEXPF:%.*]] = tail call nnan float @ldexpf(float 1.000000e+00, i16 [[TMP1]])
; LDEXP16-NEXT: ret float [[LDEXPF]]
;
; NOLDEXPF-LABEL: @sitofp_scalar_intrinsic_with_FMF(
; NOLDEXPF-NEXT: [[S:%.*]] = sitofp i8 [[X:%.*]] to float
; NOLDEXPF-NEXT: [[R:%.*]] = tail call nnan float @llvm.exp2.f32(float [[S]])
; NOLDEXPF-NEXT: ret float [[R]]
;
; NOLDEXP-LABEL: @sitofp_scalar_intrinsic_with_FMF(
; NOLDEXP-NEXT: [[S:%.*]] = sitofp i8 [[X:%.*]] to float
; NOLDEXP-NEXT: [[R:%.*]] = tail call nnan float @llvm.exp2.f32(float [[S]])
; NOLDEXP-NEXT: ret float [[R]]
;
%s = sitofp i8 %x to float
%r = tail call nnan float @llvm.exp2.f32(float %s)
ret float %r
}
; PR60605
; This would crash because there is no ldexp intrinsic.
define <2 x float> @sitofp_vector_intrinsic_with_FMF(<2 x i8> %x) {
; LDEXP32-LABEL: @sitofp_vector_intrinsic_with_FMF(
; LDEXP32-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
; LDEXP32-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
; LDEXP32-NEXT: ret <2 x float> [[R]]
;
; LDEXP16-LABEL: @sitofp_vector_intrinsic_with_FMF(
; LDEXP16-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
; LDEXP16-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
; LDEXP16-NEXT: ret <2 x float> [[R]]
;
; NOLDEXPF-LABEL: @sitofp_vector_intrinsic_with_FMF(
; NOLDEXPF-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
; NOLDEXPF-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
; NOLDEXPF-NEXT: ret <2 x float> [[R]]
;
; NOLDEXP-LABEL: @sitofp_vector_intrinsic_with_FMF(
; NOLDEXP-NEXT: [[S:%.*]] = sitofp <2 x i8> [[X:%.*]] to <2 x float>
; NOLDEXP-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> [[S]])
; NOLDEXP-NEXT: ret <2 x float> [[R]]
;
%s = sitofp <2 x i8> %x to <2 x float>
%r = call nnan <2 x float> @llvm.exp2.v2f32(<2 x float> %s)
ret <2 x float> %r
}