llvm-project/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll
Matt Arsenault fdc4274e2f
AMDGPU: Perform libcall recognition to replace fast OpenCL pow (#182135)
If a float-typed call site is marked with afn, replace the 4
flavors of pow with a faster variant.

This transforms pow, powr, pown, and rootn to __pow_fast,
__powr_fast, __pown_fast, and __rootn_fast if available. Also
attempts to handle all of the same basic folds on the new fast
variants that were already performed with the base forms. This
maintains optimizations with OpenCL when the device libs unsafe
math control library is deleted. This maintains the status quo
of how libcalls work, and only handles 4 new entry points. This
only helps with the elimination of the control library, and not
general libcall emission problems.

This makes no practical difference for HIP, which is the status
quo for libcall optimizations. AMDGPULibCalls recognizes the OpenCL
mangled names. e.g., OpenCL float "pow" is really _Z3powff but the
HIP provided function "powf" is really named _ZL4powfff, and std::pow
with float is _ZL3powff. The pass still runs for HIP, so by accident
if you used the OpenCL mangled function names, this would trigger.

Since the functions cannot yet be relied on from the library,
introduce a temporary module flag check. I'm not planning on emitting
it anywhere and it's a poor substitute for versioning the target.
2026-02-19 11:49:32 +01:00

1265 lines
56 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-simplifylib,instcombine -amdgpu-prelink %s | FileCheck -check-prefixes=CHECK,PRELINK %s
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-simplifylib,instcombine %s | FileCheck -check-prefixes=CHECK,NOPRELINK %s
declare float @_Z4pownfi(float, i32)
declare <2 x float> @_Z4pownDv2_fDv2_i(<2 x float>, <2 x i32>)
declare <3 x float> @_Z4pownDv3_fDv3_i(<3 x float>, <3 x i32>)
declare <4 x float> @_Z4pownDv4_fDv4_i(<4 x float>, <4 x i32>)
declare <8 x float> @_Z4pownDv8_fDv8_i(<8 x float>, <8 x i32>)
declare <16 x float> @_Z4pownDv16_fDv16_i(<16 x float>, <16 x i32>)
declare double @_Z4powndi(double, i32)
declare <2 x double> @_Z4pownDv2_dDv2_i(<2 x double>, <2 x i32>)
declare <3 x double> @_Z4pownDv3_dDv3_i(<3 x double>, <3 x i32>)
declare <4 x double> @_Z4pownDv4_dDv4_i(<4 x double>, <4 x i32>)
declare <8 x double> @_Z4pownDv8_dDv8_i(<8 x double>, <8 x i32>)
declare <16 x double> @_Z4pownDv16_dDv16_i(<16 x double>, <16 x i32>)
declare half @_Z4pownDhi(half, i32)
declare <2 x half> @_Z4pownDv2_DhDv2_i(<2 x half>, <2 x i32>)
declare <3 x half> @_Z4pownDv3_DhDv3_i(<3 x half>, <3 x i32>)
declare <4 x half> @_Z4pownDv4_DhDv4_i(<4 x half>, <4 x i32>)
declare <8 x half> @_Z4pownDv8_DhDv8_i(<8 x half>, <8 x i32>)
declare <16 x half> @_Z4pownDv16_DhDv16_i(<16 x half>, <16 x i32>)
define float @test_pown_f32(float %x, i32 %y) {
; CHECK-LABEL: define float @test_pown_f32
; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z4pownfi(float [[X]], i32 [[Y]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define <2 x float> @test_pown_v2f32(<2 x float> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32
; CHECK-SAME: (<2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
ret <2 x float> %call
}
define <3 x float> @test_pown_v3f32(<3 x float> %x, <3 x i32> %y) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32
; CHECK-SAME: (<3 x float> [[X:%.*]], <3 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> [[X]], <3 x i32> [[Y]])
; CHECK-NEXT: ret <3 x float> [[CALL]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> %y)
ret <3 x float> %call
}
define <4 x float> @test_pown_v4f32(<4 x float> %x, <4 x i32> %y) {
; CHECK-LABEL: define <4 x float> @test_pown_v4f32
; CHECK-SAME: (<4 x float> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x float> @_Z4pownDv4_fDv4_i(<4 x float> [[X]], <4 x i32> [[Y]])
; CHECK-NEXT: ret <4 x float> [[CALL]]
;
entry:
%call = tail call <4 x float> @_Z4pownDv4_fDv4_i(<4 x float> %x, <4 x i32> %y)
ret <4 x float> %call
}
define <8 x float> @test_pown_v8f32(<8 x float> %x, <8 x i32> %y) {
; CHECK-LABEL: define <8 x float> @test_pown_v8f32
; CHECK-SAME: (<8 x float> [[X:%.*]], <8 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x float> @_Z4pownDv8_fDv8_i(<8 x float> [[X]], <8 x i32> [[Y]])
; CHECK-NEXT: ret <8 x float> [[CALL]]
;
entry:
%call = tail call <8 x float> @_Z4pownDv8_fDv8_i(<8 x float> %x, <8 x i32> %y)
ret <8 x float> %call
}
define <16 x float> @test_pown_v16f32(<16 x float> %x, <16 x i32> %y) {
; CHECK-LABEL: define <16 x float> @test_pown_v16f32
; CHECK-SAME: (<16 x float> [[X:%.*]], <16 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x float> @_Z4pownDv16_fDv16_i(<16 x float> [[X]], <16 x i32> [[Y]])
; CHECK-NEXT: ret <16 x float> [[CALL]]
;
entry:
%call = tail call <16 x float> @_Z4pownDv16_fDv16_i(<16 x float> %x, <16 x i32> %y)
ret <16 x float> %call
}
define double @test_pown_f64(double %x, i32 %y) {
; CHECK-LABEL: define double @test_pown_f64
; CHECK-SAME: (double [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call double @_Z4powndi(double [[X]], i32 [[Y]])
; CHECK-NEXT: ret double [[CALL]]
;
entry:
%call = tail call double @_Z4powndi(double %x, i32 %y)
ret double %call
}
define <2 x double> @test_pown_v2f64(<2 x double> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x double> @test_pown_v2f64
; CHECK-SAME: (<2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x double> @_Z4pownDv2_dDv2_i(<2 x double> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x double> [[CALL]]
;
entry:
%call = tail call <2 x double> @_Z4pownDv2_dDv2_i(<2 x double> %x, <2 x i32> %y)
ret <2 x double> %call
}
define <3 x double> @test_pown_v3f64(<3 x double> %x, <3 x i32> %y) {
; CHECK-LABEL: define <3 x double> @test_pown_v3f64
; CHECK-SAME: (<3 x double> [[X:%.*]], <3 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x double> @_Z4pownDv3_dDv3_i(<3 x double> [[X]], <3 x i32> [[Y]])
; CHECK-NEXT: ret <3 x double> [[CALL]]
;
entry:
%call = tail call <3 x double> @_Z4pownDv3_dDv3_i(<3 x double> %x, <3 x i32> %y)
ret <3 x double> %call
}
define <4 x double> @test_pown_v4f64(<4 x double> %x, <4 x i32> %y) {
; CHECK-LABEL: define <4 x double> @test_pown_v4f64
; CHECK-SAME: (<4 x double> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x double> @_Z4pownDv4_dDv4_i(<4 x double> [[X]], <4 x i32> [[Y]])
; CHECK-NEXT: ret <4 x double> [[CALL]]
;
entry:
%call = tail call <4 x double> @_Z4pownDv4_dDv4_i(<4 x double> %x, <4 x i32> %y)
ret <4 x double> %call
}
define <8 x double> @test_pown_v8f64(<8 x double> %x, <8 x i32> %y) {
; CHECK-LABEL: define <8 x double> @test_pown_v8f64
; CHECK-SAME: (<8 x double> [[X:%.*]], <8 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x double> @_Z4pownDv8_dDv8_i(<8 x double> [[X]], <8 x i32> [[Y]])
; CHECK-NEXT: ret <8 x double> [[CALL]]
;
entry:
%call = tail call <8 x double> @_Z4pownDv8_dDv8_i(<8 x double> %x, <8 x i32> %y)
ret <8 x double> %call
}
define <16 x double> @test_pown_v16f64(<16 x double> %x, <16 x i32> %y) {
; CHECK-LABEL: define <16 x double> @test_pown_v16f64
; CHECK-SAME: (<16 x double> [[X:%.*]], <16 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x double> @_Z4pownDv16_dDv16_i(<16 x double> [[X]], <16 x i32> [[Y]])
; CHECK-NEXT: ret <16 x double> [[CALL]]
;
entry:
%call = tail call <16 x double> @_Z4pownDv16_dDv16_i(<16 x double> %x, <16 x i32> %y)
ret <16 x double> %call
}
define half @test_pown_f16(half %x, i32 %y) {
; CHECK-LABEL: define half @test_pown_f16
; CHECK-SAME: (half [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call half @_Z4pownDhi(half [[X]], i32 [[Y]])
; CHECK-NEXT: ret half [[CALL]]
;
entry:
%call = tail call half @_Z4pownDhi(half %x, i32 %y)
ret half %call
}
define <2 x half> @test_pown_v2f16(<2 x half> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x half> @test_pown_v2f16
; CHECK-SAME: (<2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x half> @_Z4pownDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x half> [[CALL]]
;
entry:
%call = tail call <2 x half> @_Z4pownDv2_DhDv2_i(<2 x half> %x, <2 x i32> %y)
ret <2 x half> %call
}
define <3 x half> @test_pown_v3f16(<3 x half> %x, <3 x i32> %y) {
; CHECK-LABEL: define <3 x half> @test_pown_v3f16
; CHECK-SAME: (<3 x half> [[X:%.*]], <3 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x half> @_Z4pownDv3_DhDv3_i(<3 x half> [[X]], <3 x i32> [[Y]])
; CHECK-NEXT: ret <3 x half> [[CALL]]
;
entry:
%call = tail call <3 x half> @_Z4pownDv3_DhDv3_i(<3 x half> %x, <3 x i32> %y)
ret <3 x half> %call
}
define <4 x half> @test_pown_v4f16(<4 x half> %x, <4 x i32> %y) {
; CHECK-LABEL: define <4 x half> @test_pown_v4f16
; CHECK-SAME: (<4 x half> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x half> @_Z4pownDv4_DhDv4_i(<4 x half> [[X]], <4 x i32> [[Y]])
; CHECK-NEXT: ret <4 x half> [[CALL]]
;
entry:
%call = tail call <4 x half> @_Z4pownDv4_DhDv4_i(<4 x half> %x, <4 x i32> %y)
ret <4 x half> %call
}
define <8 x half> @test_pown_v8f16(<8 x half> %x, <8 x i32> %y) {
; CHECK-LABEL: define <8 x half> @test_pown_v8f16
; CHECK-SAME: (<8 x half> [[X:%.*]], <8 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x half> @_Z4pownDv8_DhDv8_i(<8 x half> [[X]], <8 x i32> [[Y]])
; CHECK-NEXT: ret <8 x half> [[CALL]]
;
entry:
%call = tail call <8 x half> @_Z4pownDv8_DhDv8_i(<8 x half> %x, <8 x i32> %y)
ret <8 x half> %call
}
define <16 x half> @test_pown_v16f16(<16 x half> %x, <16 x i32> %y) {
; CHECK-LABEL: define <16 x half> @test_pown_v16f16
; CHECK-SAME: (<16 x half> [[X:%.*]], <16 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x half> @_Z4pownDv16_DhDv16_i(<16 x half> [[X]], <16 x i32> [[Y]])
; CHECK-NEXT: ret <16 x half> [[CALL]]
;
entry:
%call = tail call <16 x half> @_Z4pownDv16_DhDv16_i(<16 x half> %x, <16 x i32> %y)
ret <16 x half> %call
}
define float @test_pown_f32__y_0(float %x) {
; CHECK-LABEL: define float @test_pown_f32__y_0
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret float 1.000000e+00
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 0)
ret float %call
}
define float @test_pown_f32__y_poison(float %x) {
; CHECK-LABEL: define float @test_pown_f32__y_poison
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z4pownfi(float [[X]], i32 poison)
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 poison)
ret float %call
}
define <2 x float> @test_pown_v2f32__y_poison(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_poison
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> [[X]], <2 x i32> poison)
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> poison)
ret <2 x float> %call
}
define <2 x float> @test_pown_v2f32__y_0(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_0
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <2 x float> splat (float 1.000000e+00)
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> zeroinitializer)
ret <2 x float> %call
}
define <2 x float> @test_pown_v2f32__y_0_undef(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_0_undef
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <2 x float> splat (float 1.000000e+00)
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 0, i32 poison>)
ret <2 x float> %call
}
define <3 x float> @test_pown_v3f32__y_0(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_0
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <3 x float> splat (float 1.000000e+00)
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> zeroinitializer)
ret <3 x float> %call
}
define <4 x float> @test_pown_v4f32__y_0(<4 x float> %x) {
; CHECK-LABEL: define <4 x float> @test_pown_v4f32__y_0
; CHECK-SAME: (<4 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <4 x float> splat (float 1.000000e+00)
;
entry:
%call = tail call <4 x float> @_Z4pownDv4_fDv4_i(<4 x float> %x, <4 x i32> zeroinitializer)
ret <4 x float> %call
}
define <8 x float> @test_pown_v8f32__y_0(<8 x float> %x) {
; CHECK-LABEL: define <8 x float> @test_pown_v8f32__y_0
; CHECK-SAME: (<8 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <8 x float> splat (float 1.000000e+00)
;
entry:
%call = tail call <8 x float> @_Z4pownDv8_fDv8_i(<8 x float> %x, <8 x i32> zeroinitializer)
ret <8 x float> %call
}
define <16 x float> @test_pown_v16f32__y_0(<16 x float> %x) {
; CHECK-LABEL: define <16 x float> @test_pown_v16f32__y_0
; CHECK-SAME: (<16 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <16 x float> splat (float 1.000000e+00)
;
entry:
%call = tail call <16 x float> @_Z4pownDv16_fDv16_i(<16 x float> %x, <16 x i32> zeroinitializer)
ret <16 x float> %call
}
define float @test_pown_f32__y_1(float %x) {
; CHECK-LABEL: define float @test_pown_f32__y_1
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret float [[X]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 1)
ret float %call
}
define <2 x float> @test_pown_v2f32__y_1(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_1
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <2 x float> [[X]]
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 1, i32 1>)
ret <2 x float> %call
}
define <2 x float> @test_pown_v2f32__y_1_undef(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_1_undef
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <2 x float> [[X]]
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 1, i32 poison>)
ret <2 x float> %call
}
define <3 x float> @test_pown_v3f32__y_1(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_1
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <3 x float> [[X]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> <i32 1, i32 1, i32 1>)
ret <3 x float> %call
}
define <3 x float> @test_pown_v3f32__y_1_undef(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_1_undef
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <3 x float> [[X]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> <i32 1, i32 1, i32 poison>)
ret <3 x float> %call
}
define <4 x float> @test_pown_v4f32__y_1(<4 x float> %x) {
; CHECK-LABEL: define <4 x float> @test_pown_v4f32__y_1
; CHECK-SAME: (<4 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <4 x float> [[X]]
;
entry:
%call = tail call <4 x float> @_Z4pownDv4_fDv4_i(<4 x float> %x, <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
ret <4 x float> %call
}
define <8 x float> @test_pown_v8f32__y_1(<8 x float> %x) {
; CHECK-LABEL: define <8 x float> @test_pown_v8f32__y_1
; CHECK-SAME: (<8 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <8 x float> [[X]]
;
entry:
%call = tail call <8 x float> @_Z4pownDv8_fDv8_i(<8 x float> %x, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>)
ret <8 x float> %call
}
define <16 x float> @test_pown_v16f32__y_1(<16 x float> %x) {
; CHECK-LABEL: define <16 x float> @test_pown_v16f32__y_1
; CHECK-SAME: (<16 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret <16 x float> [[X]]
;
entry:
%call = tail call <16 x float> @_Z4pownDv16_fDv16_i(<16 x float> %x, <16 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>)
ret <16 x float> %call
}
define float @test_pown_f32__y_2(float %x) {
; CHECK-LABEL: define float @test_pown_f32__y_2
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul float [[X]], [[X]]
; CHECK-NEXT: ret float [[__POW2]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 2)
ret float %call
}
define <2 x float> @test_pown_v2f32__y_2(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_2
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul <2 x float> [[X]], [[X]]
; CHECK-NEXT: ret <2 x float> [[__POW2]]
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 2, i32 2>)
ret <2 x float> %call
}
define <3 x float> @test_pown_v3f32__y_2(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_2
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul <3 x float> [[X]], [[X]]
; CHECK-NEXT: ret <3 x float> [[__POW2]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> <i32 2, i32 2, i32 2>)
ret <3 x float> %call
}
define <3 x float> @test_pown_v3f32__y_2_undef(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_2_undef
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul <3 x float> [[X]], [[X]]
; CHECK-NEXT: ret <3 x float> [[__POW2]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> <i32 2, i32 poison, i32 2>)
ret <3 x float> %call
}
define <4 x float> @test_pown_v4f32__y_2(<4 x float> %x) {
; CHECK-LABEL: define <4 x float> @test_pown_v4f32__y_2
; CHECK-SAME: (<4 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul <4 x float> [[X]], [[X]]
; CHECK-NEXT: ret <4 x float> [[__POW2]]
;
entry:
%call = tail call <4 x float> @_Z4pownDv4_fDv4_i(<4 x float> %x, <4 x i32> <i32 2, i32 2, i32 2, i32 2>)
ret <4 x float> %call
}
define <8 x float> @test_pown_v8f32__y_2(<8 x float> %x) {
; CHECK-LABEL: define <8 x float> @test_pown_v8f32__y_2
; CHECK-SAME: (<8 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul <8 x float> [[X]], [[X]]
; CHECK-NEXT: ret <8 x float> [[__POW2]]
;
entry:
%call = tail call <8 x float> @_Z4pownDv8_fDv8_i(<8 x float> %x, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>)
ret <8 x float> %call
}
define <16 x float> @test_pown_v26f32__y_2(<16 x float> %x) {
; CHECK-LABEL: define <16 x float> @test_pown_v26f32__y_2
; CHECK-SAME: (<16 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POW2:%.*]] = fmul <16 x float> [[X]], [[X]]
; CHECK-NEXT: ret <16 x float> [[__POW2]]
;
entry:
%call = tail call <16 x float> @_Z4pownDv16_fDv16_i(<16 x float> %x, <16 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>)
ret <16 x float> %call
}
define float @test_pown_f32__y_neg1(float %x) {
; CHECK-LABEL: define float @test_pown_f32__y_neg1
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv float 1.000000e+00, [[X]]
; CHECK-NEXT: ret float [[__POWRECIP]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 -1)
ret float %call
}
define <2 x float> @test_pown_v2f32__y_neg1(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_v2f32__y_neg1
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv <2 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <2 x float> [[__POWRECIP]]
;
entry:
%call = tail call <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -1, i32 -1>)
ret <2 x float> %call
}
define <3 x float> @test_pown_v3f32__y_neg1(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_neg1
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv <3 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <3 x float> [[__POWRECIP]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> <i32 -1, i32 -1, i32 -1>)
ret <3 x float> %call
}
define <3 x float> @test_pown_v3f32__y_neg1_undef(<3 x float> %x) {
; CHECK-LABEL: define <3 x float> @test_pown_v3f32__y_neg1_undef
; CHECK-SAME: (<3 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv <3 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <3 x float> [[__POWRECIP]]
;
entry:
%call = tail call <3 x float> @_Z4pownDv3_fDv3_i(<3 x float> %x, <3 x i32> <i32 -1, i32 -1, i32 poison>)
ret <3 x float> %call
}
define <4 x float> @test_pown_v4f32__y_neg1(<4 x float> %x) {
; CHECK-LABEL: define <4 x float> @test_pown_v4f32__y_neg1
; CHECK-SAME: (<4 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv <4 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <4 x float> [[__POWRECIP]]
;
entry:
%call = tail call <4 x float> @_Z4pownDv4_fDv4_i(<4 x float> %x, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
ret <4 x float> %call
}
define <8 x float> @test_pown_v8f32__y_neg1(<8 x float> %x) {
; CHECK-LABEL: define <8 x float> @test_pown_v8f32__y_neg1
; CHECK-SAME: (<8 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv <8 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <8 x float> [[__POWRECIP]]
;
entry:
%call = tail call <8 x float> @_Z4pownDv8_fDv8_i(<8 x float> %x, <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>)
ret <8 x float> %call
}
define <16 x float> @test_pown_v16f32__y_neg1(<16 x float> %x) {
; CHECK-LABEL: define <16 x float> @test_pown_v16f32__y_neg1
; CHECK-SAME: (<16 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWRECIP:%.*]] = fdiv <16 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <16 x float> [[__POWRECIP]]
;
entry:
%call = tail call <16 x float> @_Z4pownDv16_fDv16_i(<16 x float> %x, <16 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>)
ret <16 x float> %call
}
define float @test_pown_afn_f32(float %x, i32 %y) {
; PRELINK-LABEL: define float @test_pown_afn_f32
; PRELINK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[CALL:%.*]] = tail call afn float @_Z11__pown_fastfi(float [[X]], i32 [[Y]])
; PRELINK-NEXT: ret float [[CALL]]
;
; NOPRELINK-LABEL: define float @test_pown_afn_f32
; NOPRELINK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[Y]], 0
; NOPRELINK-NEXT: [[TMP1:%.*]] = select afn i1 [[TMP0]], float 1.000000e+00, float [[X]]
; NOPRELINK-NEXT: [[TMP2:%.*]] = sitofp i32 [[Y]] to float
; NOPRELINK-NEXT: [[TMP3:%.*]] = call afn float @llvm.fabs.f32(float [[TMP1]])
; NOPRELINK-NEXT: [[TMP4:%.*]] = call afn float @llvm.log2.f32(float [[TMP3]])
; NOPRELINK-NEXT: [[TMP5:%.*]] = fmul afn float [[TMP4]], [[TMP2]]
; NOPRELINK-NEXT: [[TMP6:%.*]] = call afn float @llvm.exp2.f32(float [[TMP5]])
; NOPRELINK-NEXT: [[TMP7:%.*]] = and i32 [[Y]], 1
; NOPRELINK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP7]], 0
; NOPRELINK-NEXT: [[TMP8:%.*]] = select afn i1 [[DOTNOT]], float 1.000000e+00, float [[TMP1]]
; NOPRELINK-NEXT: [[TMP9:%.*]] = call afn float @llvm.copysign.f32(float [[TMP6]], float [[TMP8]])
; NOPRELINK-NEXT: [[TMP10:%.*]] = call afn float @llvm.fabs.f32(float [[TMP1]])
; NOPRELINK-NEXT: [[TMP11:%.*]] = fcmp afn oeq float [[TMP10]], 0x7FF0000000000000
; NOPRELINK-NEXT: [[TMP12:%.*]] = fcmp afn oeq float [[TMP1]], 0.000000e+00
; NOPRELINK-NEXT: [[TMP13:%.*]] = or i1 [[TMP11]], [[TMP12]]
; NOPRELINK-NEXT: [[TMP14:%.*]] = icmp slt i32 [[Y]], 0
; NOPRELINK-NEXT: [[TMP15:%.*]] = xor i1 [[TMP12]], [[TMP14]]
; NOPRELINK-NEXT: [[TMP16:%.*]] = select afn i1 [[TMP15]], float 0.000000e+00, float 0x7FF0000000000000
; NOPRELINK-NEXT: [[TMP17:%.*]] = select afn i1 [[DOTNOT]], float 0.000000e+00, float [[TMP1]]
; NOPRELINK-NEXT: [[TMP18:%.*]] = call afn float @llvm.copysign.f32(float [[TMP16]], float [[TMP17]])
; NOPRELINK-NEXT: [[TMP19:%.*]] = select afn i1 [[TMP13]], float [[TMP18]], float [[TMP9]]
; NOPRELINK-NEXT: ret float [[TMP19]]
;
entry:
%call = tail call afn float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define <2 x float> @test_pown_afn_v2f32(<2 x float> %x, <2 x i32> %y) {
; PRELINK-LABEL: define <2 x float> @test_pown_afn_v2f32
; PRELINK-SAME: (<2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[CALL:%.*]] = tail call afn <2 x float> @_Z11__pown_fastDv2_fDv2_i(<2 x float> [[X]], <2 x i32> [[Y]])
; PRELINK-NEXT: ret <2 x float> [[CALL]]
;
; NOPRELINK-LABEL: define <2 x float> @test_pown_afn_v2f32
; NOPRELINK-SAME: (<2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[TMP0:%.*]] = icmp eq <2 x i32> [[Y]], zeroinitializer
; NOPRELINK-NEXT: [[TMP1:%.*]] = select afn <2 x i1> [[TMP0]], <2 x float> splat (float 1.000000e+00), <2 x float> [[X]]
; NOPRELINK-NEXT: [[TMP2:%.*]] = sitofp <2 x i32> [[Y]] to <2 x float>
; NOPRELINK-NEXT: [[TMP3:%.*]] = call afn <2 x float> @llvm.fabs.v2f32(<2 x float> [[TMP1]])
; NOPRELINK-NEXT: [[TMP4:%.*]] = call afn <2 x float> @llvm.log2.v2f32(<2 x float> [[TMP3]])
; NOPRELINK-NEXT: [[TMP5:%.*]] = fmul afn <2 x float> [[TMP4]], [[TMP2]]
; NOPRELINK-NEXT: [[TMP6:%.*]] = call afn <2 x float> @llvm.exp2.v2f32(<2 x float> [[TMP5]])
; NOPRELINK-NEXT: [[TMP7:%.*]] = and <2 x i32> [[Y]], splat (i32 1)
; NOPRELINK-NEXT: [[DOTNOT:%.*]] = icmp eq <2 x i32> [[TMP7]], zeroinitializer
; NOPRELINK-NEXT: [[TMP8:%.*]] = select afn <2 x i1> [[DOTNOT]], <2 x float> splat (float 1.000000e+00), <2 x float> [[TMP1]]
; NOPRELINK-NEXT: [[TMP9:%.*]] = call afn <2 x float> @llvm.copysign.v2f32(<2 x float> [[TMP6]], <2 x float> [[TMP8]])
; NOPRELINK-NEXT: [[TMP10:%.*]] = call afn <2 x float> @llvm.fabs.v2f32(<2 x float> [[TMP1]])
; NOPRELINK-NEXT: [[TMP11:%.*]] = fcmp afn oeq <2 x float> [[TMP10]], splat (float 0x7FF0000000000000)
; NOPRELINK-NEXT: [[TMP12:%.*]] = fcmp afn oeq <2 x float> [[TMP1]], zeroinitializer
; NOPRELINK-NEXT: [[TMP13:%.*]] = or <2 x i1> [[TMP11]], [[TMP12]]
; NOPRELINK-NEXT: [[TMP14:%.*]] = icmp slt <2 x i32> [[Y]], zeroinitializer
; NOPRELINK-NEXT: [[TMP15:%.*]] = xor <2 x i1> [[TMP12]], [[TMP14]]
; NOPRELINK-NEXT: [[TMP16:%.*]] = select afn <2 x i1> [[TMP15]], <2 x float> zeroinitializer, <2 x float> splat (float 0x7FF0000000000000)
; NOPRELINK-NEXT: [[TMP17:%.*]] = select afn <2 x i1> [[DOTNOT]], <2 x float> zeroinitializer, <2 x float> [[TMP1]]
; NOPRELINK-NEXT: [[TMP18:%.*]] = call afn <2 x float> @llvm.copysign.v2f32(<2 x float> [[TMP16]], <2 x float> [[TMP17]])
; NOPRELINK-NEXT: [[TMP19:%.*]] = select afn <2 x i1> [[TMP13]], <2 x float> [[TMP18]], <2 x float> [[TMP9]]
; NOPRELINK-NEXT: ret <2 x float> [[TMP19]]
;
entry:
%call = tail call afn <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
ret <2 x float> %call
}
define double @test_pown_afn_f64(double %x, i32 %y) {
; CHECK-LABEL: define double @test_pown_afn_f64
; CHECK-SAME: (double [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call afn double @_Z4powndi(double [[X]], i32 [[Y]])
; CHECK-NEXT: ret double [[CALL]]
;
entry:
%call = tail call afn double @_Z4powndi(double %x, i32 %y)
ret double %call
}
define <2 x double> @test_pown_afn_v2f64(<2 x double> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x double> @test_pown_afn_v2f64
; CHECK-SAME: (<2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <2 x double> @_Z4pownDv2_dDv2_i(<2 x double> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x double> [[CALL]]
;
entry:
%call = tail call afn <2 x double> @_Z4pownDv2_dDv2_i(<2 x double> %x, <2 x i32> %y)
ret <2 x double> %call
}
define half @test_pown_afn_f16(half %x, i32 %y) {
; CHECK-LABEL: define half @test_pown_afn_f16
; CHECK-SAME: (half [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call afn half @_Z4pownDhi(half [[X]], i32 [[Y]])
; CHECK-NEXT: ret half [[CALL]]
;
entry:
%call = tail call afn half @_Z4pownDhi(half %x, i32 %y)
ret half %call
}
define <2 x half> @test_pown_afn_v2f16(<2 x half> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x half> @test_pown_afn_v2f16
; CHECK-SAME: (<2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <2 x half> @_Z4pownDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x half> [[CALL]]
;
entry:
%call = tail call afn <2 x half> @_Z4pownDv2_DhDv2_i(<2 x half> %x, <2 x i32> %y)
ret <2 x half> %call
}
define float @test_pown_afn_nnan_ninf_f32(float %x, i32 %y) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32
; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__FABS:%.*]] = call nnan ninf afn float @llvm.fabs.f32(float [[X]])
; CHECK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn float @llvm.log2.f32(float [[__FABS]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to float
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn float [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[__YLOGX]])
; CHECK-NEXT: [[__YEVEN:%.*]] = shl i32 [[Y]], 31
; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32
; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[__POW_SIGN]] to float
; CHECK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn float @llvm.copysign.f32(float [[__EXP2]], float [[TMP1]])
; CHECK-NEXT: ret float [[__POW_SIGN1]]
;
entry:
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define <2 x float> @test_pown_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x float> @test_pown_afn_nnan_ninf_v2f32
; CHECK-SAME: (<2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__FABS:%.*]] = call nnan ninf afn <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
; CHECK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn <2 x float> @llvm.log2.v2f32(<2 x float> [[__FABS]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp <2 x i32> [[Y]] to <2 x float>
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn <2 x float> [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) <2 x float> @llvm.exp2.v2f32(<2 x float> [[__YLOGX]])
; CHECK-NEXT: [[__YEVEN:%.*]] = shl <2 x i32> [[Y]], splat (i32 31)
; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[X]] to <2 x i32>
; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[__POW_SIGN]] to <2 x float>
; CHECK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn <2 x float> @llvm.copysign.v2f32(<2 x float> [[__EXP2]], <2 x float> [[TMP1]])
; CHECK-NEXT: ret <2 x float> [[__POW_SIGN1]]
;
entry:
%call = tail call nnan ninf afn <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
ret <2 x float> %call
}
define double @test_pown_afn_nnan_ninf_f64(double %x, i32 %y) {
; PRELINK-LABEL: define double @test_pown_afn_nnan_ninf_f64
; PRELINK-SAME: (double [[X:%.*]], i32 [[Y:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[__FABS:%.*]] = call nnan ninf afn double @llvm.fabs.f64(double [[X]])
; PRELINK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn double @_Z4log2d(double [[__FABS]])
; PRELINK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to double
; PRELINK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn double [[__LOG2]], [[POWNI2F]]
; PRELINK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) double @_Z4exp2d(double [[__YLOGX]])
; PRELINK-NEXT: [[__YTOU:%.*]] = zext i32 [[Y]] to i64
; PRELINK-NEXT: [[__YEVEN:%.*]] = shl i64 [[__YTOU]], 63
; PRELINK-NEXT: [[TMP0:%.*]] = bitcast double [[X]] to i64
; PRELINK-NEXT: [[__POW_SIGN:%.*]] = and i64 [[__YEVEN]], [[TMP0]]
; PRELINK-NEXT: [[TMP1:%.*]] = bitcast i64 [[__POW_SIGN]] to double
; PRELINK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn double @llvm.copysign.f64(double [[__EXP2]], double [[TMP1]])
; PRELINK-NEXT: ret double [[__POW_SIGN1]]
;
; NOPRELINK-LABEL: define double @test_pown_afn_nnan_ninf_f64
; NOPRELINK-SAME: (double [[X:%.*]], i32 [[Y:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn double @_Z4powndi(double [[X]], i32 [[Y]])
; NOPRELINK-NEXT: ret double [[CALL]]
;
entry:
%call = tail call nnan ninf afn double @_Z4powndi(double %x, i32 %y)
ret double %call
}
define <2 x double> @test_pown_afn_nnan_ninf_v2f64(<2 x double> %x, <2 x i32> %y) {
; PRELINK-LABEL: define <2 x double> @test_pown_afn_nnan_ninf_v2f64
; PRELINK-SAME: (<2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[__FABS:%.*]] = call nnan ninf afn <2 x double> @llvm.fabs.v2f64(<2 x double> [[X]])
; PRELINK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn <2 x double> @_Z4log2Dv2_d(<2 x double> [[__FABS]])
; PRELINK-NEXT: [[POWNI2F:%.*]] = sitofp <2 x i32> [[Y]] to <2 x double>
; PRELINK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn <2 x double> [[__LOG2]], [[POWNI2F]]
; PRELINK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) <2 x double> @_Z4exp2Dv2_d(<2 x double> [[__YLOGX]])
; PRELINK-NEXT: [[__YTOU:%.*]] = zext <2 x i32> [[Y]] to <2 x i64>
; PRELINK-NEXT: [[__YEVEN:%.*]] = shl <2 x i64> [[__YTOU]], splat (i64 63)
; PRELINK-NEXT: [[TMP0:%.*]] = bitcast <2 x double> [[X]] to <2 x i64>
; PRELINK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i64> [[__YEVEN]], [[TMP0]]
; PRELINK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[__POW_SIGN]] to <2 x double>
; PRELINK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn <2 x double> @llvm.copysign.v2f64(<2 x double> [[__EXP2]], <2 x double> [[TMP1]])
; PRELINK-NEXT: ret <2 x double> [[__POW_SIGN1]]
;
; NOPRELINK-LABEL: define <2 x double> @test_pown_afn_nnan_ninf_v2f64
; NOPRELINK-SAME: (<2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn <2 x double> @_Z4pownDv2_dDv2_i(<2 x double> [[X]], <2 x i32> [[Y]])
; NOPRELINK-NEXT: ret <2 x double> [[CALL]]
;
entry:
%call = tail call nnan ninf afn <2 x double> @_Z4pownDv2_dDv2_i(<2 x double> %x, <2 x i32> %y)
ret <2 x double> %call
}
define half @test_pown_afn_nnan_ninf_f16(half %x, i32 %y) {
; CHECK-LABEL: define half @test_pown_afn_nnan_ninf_f16
; CHECK-SAME: (half [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__FABS:%.*]] = call nnan ninf afn half @llvm.fabs.f16(half [[X]])
; CHECK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn half @llvm.log2.f16(half [[__FABS]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to half
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn half [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) half @llvm.exp2.f16(half [[__YLOGX]])
; CHECK-NEXT: [[__YTOU:%.*]] = trunc i32 [[Y]] to i16
; CHECK-NEXT: [[__YEVEN:%.*]] = shl i16 [[__YTOU]], 15
; CHECK-NEXT: [[TMP0:%.*]] = bitcast half [[X]] to i16
; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i16 [[__YEVEN]], [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i16 [[__POW_SIGN]] to half
; CHECK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn half @llvm.copysign.f16(half [[__EXP2]], half [[TMP1]])
; CHECK-NEXT: ret half [[__POW_SIGN1]]
;
entry:
%call = tail call nnan ninf afn half @_Z4pownDhi(half %x, i32 %y)
ret half %call
}
define <2 x half> @test_pown_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) {
; CHECK-LABEL: define <2 x half> @test_pown_afn_nnan_ninf_v2f16
; CHECK-SAME: (<2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__FABS:%.*]] = call nnan ninf afn <2 x half> @llvm.fabs.v2f16(<2 x half> [[X]])
; CHECK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn <2 x half> @llvm.log2.v2f16(<2 x half> [[__FABS]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp <2 x i32> [[Y]] to <2 x half>
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn <2 x half> [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) <2 x half> @llvm.exp2.v2f16(<2 x half> [[__YLOGX]])
; CHECK-NEXT: [[__YTOU:%.*]] = trunc <2 x i32> [[Y]] to <2 x i16>
; CHECK-NEXT: [[__YEVEN:%.*]] = shl <2 x i16> [[__YTOU]], splat (i16 15)
; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x half> [[X]] to <2 x i16>
; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i16> [[__YEVEN]], [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i16> [[__POW_SIGN]] to <2 x half>
; CHECK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn <2 x half> @llvm.copysign.v2f16(<2 x half> [[__EXP2]], <2 x half> [[TMP1]])
; CHECK-NEXT: ret <2 x half> [[__POW_SIGN1]]
;
entry:
%call = tail call nnan ninf afn <2 x half> @_Z4pownDv2_DhDv2_i(<2 x half> %x, <2 x i32> %y)
ret <2 x half> %call
}
define float @test_pown_fast_f32_nobuiltin(float %x, i32 %y) {
; PRELINK-LABEL: define float @test_pown_fast_f32_nobuiltin
; PRELINK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[CALL:%.*]] = tail call fast float @_Z4pownfi(float [[X]], i32 [[Y]]) #[[ATTR4:[0-9]+]]
; PRELINK-NEXT: ret float [[CALL]]
;
; NOPRELINK-LABEL: define float @test_pown_fast_f32_nobuiltin
; NOPRELINK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[CALL:%.*]] = tail call fast float @_Z4pownfi(float [[X]], i32 [[Y]]) #[[ATTR3:[0-9]+]]
; NOPRELINK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call fast float @_Z4pownfi(float %x, i32 %y) #0
ret float %call
}
define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 {
; CHECK-LABEL: define float @test_pown_fast_f32_strictfp
; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) #[[ATTR0]]
; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[__FABS]]) #[[ATTR0]]
; CHECK-NEXT: [[POWNI2F:%.*]] = call fast float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
; CHECK-NEXT: [[__YLOGX:%.*]] = call fast float @llvm.experimental.constrained.fmul.f32(float [[POWNI2F]], float [[__LOG2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
; CHECK-NEXT: [[__EXP2:%.*]] = call fast nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[__YLOGX]]) #[[ATTR0]]
; CHECK-NEXT: [[__YEVEN:%.*]] = shl i32 [[Y]], 31
; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32
; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[__POW_SIGN]] to float
; CHECK-NEXT: [[__POW_SIGN1:%.*]] = call fast float @llvm.copysign.f32(float [[__EXP2]], float [[TMP1]]) #[[ATTR0]]
; CHECK-NEXT: ret float [[__POW_SIGN1]]
;
entry:
%call = tail call fast float @_Z4pownfi(float %x, i32 %y) #1
ret float %call
}
define float @test_pown_fast_f32__y_poison(float %x) {
; CHECK-LABEL: define float @test_pown_fast_f32__y_poison
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: ret float poison
;
%call = tail call fast float @_Z4pownfi(float %x, i32 poison)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_3(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_3
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn float [[X]], [[__POWX2]]
; CHECK-NEXT: ret float [[__POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 3)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_neg3(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_neg3
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn float [[X]], [[__POWX2]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn float 1.000000e+00, [[__POWPROD]]
; CHECK-NEXT: ret float [[__1POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 -3)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_4(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_4
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: ret float [[__POWX21]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 4)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_neg4(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_neg4
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn float 1.000000e+00, [[__POWX21]]
; CHECK-NEXT: ret float [[__1POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 -4)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_5(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_5
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn float [[X]], [[__POWX21]]
; CHECK-NEXT: ret float [[__POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 5)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_neg5(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_neg5
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn float [[X]], [[__POWX21]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn float 1.000000e+00, [[__POWPROD]]
; CHECK-NEXT: ret float [[__1POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 -5)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_7(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_7
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn float [[X]], [[__POWX2]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWPROD2:%.*]] = fmul nnan ninf afn float [[__POWPROD]], [[__POWX21]]
; CHECK-NEXT: ret float [[__POWPROD2]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 7)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_neg7(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_neg7
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn float [[X]], [[__POWX2]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWPROD2:%.*]] = fmul nnan ninf afn float [[__POWPROD]], [[__POWX21]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn float 1.000000e+00, [[__POWPROD2]]
; CHECK-NEXT: ret float [[__1POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 -7)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_8(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_8
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWX22:%.*]] = fmul nnan ninf afn float [[__POWX21]], [[__POWX21]]
; CHECK-NEXT: ret float [[__POWX22]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 8)
ret float %call
}
define float @test_pown_afn_nnan_ninf_f32__y_neg8(float %x) {
; CHECK-LABEL: define float @test_pown_afn_nnan_ninf_f32__y_neg8
; CHECK-SAME: (float [[X:%.*]]) {
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn float [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn float [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWX22:%.*]] = fmul nnan ninf afn float [[__POWX21]], [[__POWX21]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn float 1.000000e+00, [[__POWX22]]
; CHECK-NEXT: ret float [[__1POWPROD]]
;
%call = tail call nnan ninf afn float @_Z4pownfi(float %x, i32 -8)
ret float %call
}
define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_3(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_3
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[X]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[__POWX2]]
; CHECK-NEXT: ret <2 x float> [[__POWPROD]]
;
entry:
%call = tail call afn nnan ninf <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 3, i32 3>)
ret <2 x float> %call
}
define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_4(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_4
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn <2 x float> [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: ret <2 x float> [[__POWX21]]
;
entry:
%call = tail call afn nnan ninf <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 4, i32 4>)
ret <2 x float> %call
}
define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_neg3(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_neg3
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[X]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[__POWX2]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn <2 x float> splat (float 1.000000e+00), [[__POWPROD]]
; CHECK-NEXT: ret <2 x float> [[__1POWPROD]]
;
entry:
%call = tail call afn nnan ninf <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -3, i32 -3>)
ret <2 x float> %call
}
define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_neg4(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_neg4
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn <2 x float> [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__1POWPROD:%.*]] = fdiv nnan ninf afn <2 x float> splat (float 1.000000e+00), [[__POWX21]]
; CHECK-NEXT: ret <2 x float> [[__1POWPROD]]
;
entry:
%call = tail call afn nnan ninf <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -4, i32 -4>)
ret <2 x float> %call
}
define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_5(<2 x float> %x) {
; CHECK-LABEL: define <2 x float> @test_pown_afn_nnan_ninf_v2f32__y_5
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__POWX2:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[X]]
; CHECK-NEXT: [[__POWX21:%.*]] = fmul nnan ninf afn <2 x float> [[__POWX2]], [[__POWX2]]
; CHECK-NEXT: [[__POWPROD:%.*]] = fmul nnan ninf afn <2 x float> [[X]], [[__POWX21]]
; CHECK-NEXT: ret <2 x float> [[__POWPROD]]
;
entry:
%call = tail call afn nnan ninf <2 x float> @_Z4pownDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 5, i32 5>)
ret <2 x float> %call
}
define float @test_pown_f32__x_known_positive(float nofpclass(ninf nsub nnorm) %x, i32 %y) {
; CHECK-LABEL: define float @test_pown_f32__x_known_positive
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z4pownfi(float [[X]], i32 [[Y]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define float @test_pown_afn_f32__x_known_positive(float nofpclass(ninf nsub nnorm) %x, i32 %y) {
; PRELINK-LABEL: define float @test_pown_afn_f32__x_known_positive
; PRELINK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[CALL:%.*]] = tail call afn float @_Z11__pown_fastfi(float [[X]], i32 [[Y]])
; PRELINK-NEXT: ret float [[CALL]]
;
; NOPRELINK-LABEL: define float @test_pown_afn_f32__x_known_positive
; NOPRELINK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[Y]], 0
; NOPRELINK-NEXT: [[TMP1:%.*]] = select afn i1 [[TMP0]], float 1.000000e+00, float [[X]]
; NOPRELINK-NEXT: [[TMP2:%.*]] = sitofp i32 [[Y]] to float
; NOPRELINK-NEXT: [[TMP3:%.*]] = call afn float @llvm.fabs.f32(float [[TMP1]])
; NOPRELINK-NEXT: [[TMP4:%.*]] = call afn float @llvm.log2.f32(float [[TMP3]])
; NOPRELINK-NEXT: [[TMP5:%.*]] = fmul afn float [[TMP4]], [[TMP2]]
; NOPRELINK-NEXT: [[TMP6:%.*]] = call afn float @llvm.exp2.f32(float [[TMP5]])
; NOPRELINK-NEXT: [[TMP7:%.*]] = and i32 [[Y]], 1
; NOPRELINK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP7]], 0
; NOPRELINK-NEXT: [[TMP8:%.*]] = select afn i1 [[DOTNOT]], float 1.000000e+00, float [[TMP1]]
; NOPRELINK-NEXT: [[TMP9:%.*]] = call afn float @llvm.copysign.f32(float [[TMP6]], float [[TMP8]])
; NOPRELINK-NEXT: [[TMP10:%.*]] = call afn float @llvm.fabs.f32(float [[TMP1]])
; NOPRELINK-NEXT: [[TMP11:%.*]] = fcmp afn oeq float [[TMP10]], 0x7FF0000000000000
; NOPRELINK-NEXT: [[TMP12:%.*]] = fcmp afn oeq float [[TMP1]], 0.000000e+00
; NOPRELINK-NEXT: [[TMP13:%.*]] = or i1 [[TMP11]], [[TMP12]]
; NOPRELINK-NEXT: [[TMP14:%.*]] = icmp slt i32 [[Y]], 0
; NOPRELINK-NEXT: [[TMP15:%.*]] = xor i1 [[TMP12]], [[TMP14]]
; NOPRELINK-NEXT: [[TMP16:%.*]] = select afn i1 [[TMP15]], float 0.000000e+00, float 0x7FF0000000000000
; NOPRELINK-NEXT: [[TMP17:%.*]] = select afn i1 [[DOTNOT]], float 0.000000e+00, float [[TMP1]]
; NOPRELINK-NEXT: [[TMP18:%.*]] = call afn float @llvm.copysign.f32(float [[TMP16]], float [[TMP17]])
; NOPRELINK-NEXT: [[TMP19:%.*]] = select afn i1 [[TMP13]], float [[TMP18]], float [[TMP9]]
; NOPRELINK-NEXT: ret float [[TMP19]]
;
entry:
%call = tail call afn float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define float @test_pown_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf nsub nnorm) %x, i32 %y) {
; CHECK-LABEL: define float @test_pown_afn_ninf_nnan_f32__x_known_positive
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[__LOG2:%.*]] = call nnan ninf afn float @llvm.log2.f32(float [[X]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to float
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul nnan ninf afn float [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call nnan ninf afn nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[__YLOGX]])
; CHECK-NEXT: [[__YEVEN:%.*]] = shl i32 [[Y]], 31
; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32
; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[__POW_SIGN]] to float
; CHECK-NEXT: [[__POW_SIGN1:%.*]] = call nnan ninf afn float @llvm.copysign.f32(float [[__EXP2]], float [[TMP1]])
; CHECK-NEXT: ret float [[__POW_SIGN1]]
;
entry:
%call = tail call afn ninf nnan float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define float @test_pown_afn_f32__x_known_positive__y_4(float nofpclass(ninf nsub nnorm) %x) {
; PRELINK-LABEL: define float @test_pown_afn_f32__x_known_positive__y_4
; PRELINK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]]) {
; PRELINK-NEXT: entry:
; PRELINK-NEXT: [[CALL:%.*]] = tail call afn float @_Z11__pown_fastfi(float [[X]], i32 4)
; PRELINK-NEXT: ret float [[CALL]]
;
; NOPRELINK-LABEL: define float @test_pown_afn_f32__x_known_positive__y_4
; NOPRELINK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]]) {
; NOPRELINK-NEXT: entry:
; NOPRELINK-NEXT: [[TMP0:%.*]] = call afn float @llvm.fabs.f32(float [[X]])
; NOPRELINK-NEXT: [[TMP1:%.*]] = call afn float @llvm.log2.f32(float [[TMP0]])
; NOPRELINK-NEXT: [[TMP2:%.*]] = fmul afn float [[TMP1]], 4.000000e+00
; NOPRELINK-NEXT: [[TMP3:%.*]] = call afn float @llvm.exp2.f32(float [[TMP2]])
; NOPRELINK-NEXT: [[TMP4:%.*]] = call afn float @llvm.fabs.f32(float [[TMP3]])
; NOPRELINK-NEXT: [[TMP5:%.*]] = call afn float @llvm.fabs.f32(float [[X]])
; NOPRELINK-NEXT: [[TMP6:%.*]] = fcmp afn oeq float [[TMP5]], 0x7FF0000000000000
; NOPRELINK-NEXT: [[TMP7:%.*]] = fcmp afn oeq float [[X]], 0.000000e+00
; NOPRELINK-NEXT: [[TMP8:%.*]] = select i1 [[TMP6]], float 0x7FF0000000000000, float [[TMP4]]
; NOPRELINK-NEXT: [[TMP9:%.*]] = select i1 [[TMP7]], float 0.000000e+00, float [[TMP8]]
; NOPRELINK-NEXT: ret float [[TMP9]]
;
entry:
%call = tail call afn float @_Z4pownfi(float %x, i32 4)
ret float %call
}
define float @test_pown_f32__x_known_positive__y_4(float nofpclass(ninf nsub nnorm) %x) {
; CHECK-LABEL: define float @test_pown_f32__x_known_positive__y_4
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z4pownfi(float [[X]], i32 4)
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call float @_Z4pownfi(float %x, i32 4)
ret float %call
}
define float @test_pown_f32_y_known_even(float %x, i32 %y.arg) {
; CHECK-LABEL: define float @test_pown_f32_y_known_even
; CHECK-SAME: (float [[X:%.*]], i32 [[Y_ARG:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y:%.*]] = shl i32 [[Y_ARG]], 1
; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z4pownfi(float [[X]], i32 [[Y]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%y = shl i32 %y.arg, 1
%call = tail call float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define float @test_fast_pown_f32_y_known_even(float %x, i32 %y.arg) {
; CHECK-LABEL: define float @test_fast_pown_f32_y_known_even
; CHECK-SAME: (float [[X:%.*]], i32 [[Y_ARG:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y:%.*]] = shl i32 [[Y_ARG]], 1
; CHECK-NEXT: [[__FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]])
; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[__FABS]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to float
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul fast float [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call fast nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[__YLOGX]])
; CHECK-NEXT: ret float [[__EXP2]]
;
entry:
%y = shl i32 %y.arg, 1
%call = tail call fast float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
define float @test_fast_pown_f32_known_positive_y_known_even(float nofpclass(ninf nsub nnorm) %x, i32 %y.arg) {
; CHECK-LABEL: define float @test_fast_pown_f32_known_positive_y_known_even
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y_ARG:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[Y:%.*]] = shl i32 [[Y_ARG]], 1
; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[X]])
; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to float
; CHECK-NEXT: [[__YLOGX:%.*]] = fmul fast float [[__LOG2]], [[POWNI2F]]
; CHECK-NEXT: [[__EXP2:%.*]] = call fast nofpclass(nan ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[__YLOGX]])
; CHECK-NEXT: ret float [[__EXP2]]
;
entry:
%y = shl i32 %y.arg, 1
%call = tail call fast float @_Z4pownfi(float %x, i32 %y)
ret float %call
}
attributes #0 = { nobuiltin }
attributes #1 = { strictfp }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"amdgpu-libcall-have-fast-pow", i32 1}