llvm-project/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn-fast.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

453 lines
17 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-simplifylib,instcombine -amdgpu-prelink %s | FileCheck %s
define float @test_rootn_afn_f32(float %x, i32 %y) #0 {
; CHECK-LABEL: define float @test_rootn_afn_f32(
; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn float @_Z12__rootn_fastfi(float [[X]], i32 [[Y]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call afn float @_Z5rootnfi(float %x, i32 %y)
ret float %call
}
declare float @_Z5rootnfi(float, i32) #1
define <2 x float> @test_rootn_afn_v2f32(<2 x float> %x, <2 x i32> %y) #0 {
; CHECK-LABEL: define <2 x float> @test_rootn_afn_v2f32(
; CHECK-SAME: <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <2 x float> @_Z12__rootn_fastDv2_fDv2_i(<2 x float> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
entry:
%call = tail call afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
ret <2 x float> %call
}
declare <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float>, <2 x i32>) #1
define <3 x float> @test_rootn_afn_v3f32(<3 x float> %x, <3 x i32> %y) #0 {
; CHECK-LABEL: define <3 x float> @test_rootn_afn_v3f32(
; CHECK-SAME: <3 x float> [[X:%.*]], <3 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <3 x float> @_Z12__rootn_fastDv3_fDv3_i(<3 x float> [[X]], <3 x i32> [[Y]])
; CHECK-NEXT: ret <3 x float> [[CALL]]
;
entry:
%call = tail call afn <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> %y)
ret <3 x float> %call
}
declare <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float>, <3 x i32>) #1
define <4 x float> @test_rootn_afn_v4f32(<4 x float> %x, <4 x i32> %y) #0 {
; CHECK-LABEL: define <4 x float> @test_rootn_afn_v4f32(
; CHECK-SAME: <4 x float> [[X:%.*]], <4 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <4 x float> @_Z12__rootn_fastDv4_fDv4_i(<4 x float> [[X]], <4 x i32> [[Y]])
; CHECK-NEXT: ret <4 x float> [[CALL]]
;
entry:
%call = tail call afn <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> %x, <4 x i32> %y)
ret <4 x float> %call
}
declare <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float>, <4 x i32>) #1
define <8 x float> @test_rootn_afn_v8f32(<8 x float> %x, <8 x i32> %y) #0 {
; CHECK-LABEL: define <8 x float> @test_rootn_afn_v8f32(
; CHECK-SAME: <8 x float> [[X:%.*]], <8 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <8 x float> @_Z12__rootn_fastDv8_fDv8_i(<8 x float> [[X]], <8 x i32> [[Y]])
; CHECK-NEXT: ret <8 x float> [[CALL]]
;
entry:
%call = tail call afn <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> %x, <8 x i32> %y)
ret <8 x float> %call
}
declare <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float>, <8 x i32>) #1
define <16 x float> @test_rootn_afn_v16f32(<16 x float> %x, <16 x i32> %y) #0 {
; CHECK-LABEL: define <16 x float> @test_rootn_afn_v16f32(
; CHECK-SAME: <16 x float> [[X:%.*]], <16 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <16 x float> @_Z12__rootn_fastDv16_fDv16_i(<16 x float> [[X]], <16 x i32> [[Y]])
; CHECK-NEXT: ret <16 x float> [[CALL]]
;
entry:
%call = tail call afn <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> %x, <16 x i32> %y)
ret <16 x float> %call
}
declare <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float>, <16 x i32>) #1
define float @test_rootn_afn_f32__2(float %x) #0 {
; CHECK-LABEL: define float @test_rootn_afn_f32__2(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call afn float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0:![0-9]+]]
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call afn float @_Z5rootnfi(float %x, i32 2)
ret float %call
}
define float @test_rootn_afn_f32__3(float %x) #0 {
; CHECK-LABEL: define float @test_rootn_afn_f32__3(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2CBRT:%.*]] = call afn float @_Z4cbrtf(float [[X]])
; CHECK-NEXT: ret float [[__ROOTN2CBRT]]
;
entry:
%call = tail call afn float @_Z5rootnfi(float %x, i32 3)
ret float %call
}
define float @test_rootn_afn_f32__neg1(float %x) #0 {
; CHECK-LABEL: define float @test_rootn_afn_f32__neg1(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv afn float 1.000000e+00, [[X]]
; CHECK-NEXT: ret float [[__ROOTN2DIV]]
;
entry:
%call = tail call afn float @_Z5rootnfi(float %x, i32 -1)
ret float %call
}
define float @test_rootn_afn_f32__neg2(float %x) #0 {
; CHECK-LABEL: define float @test_rootn_afn_f32__neg2(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = call contract afn float @llvm.sqrt.f32(float [[X]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv contract afn float 1.000000e+00, [[TMP0]], !fpmath [[META0]]
; CHECK-NEXT: ret float [[TMP1]]
;
entry:
%call = tail call afn float @_Z5rootnfi(float %x, i32 -2)
ret float %call
}
define <2 x float> @test_rootn_afn_v2f32__2(<2 x float> %x) #0 {
; CHECK-LABEL: define <2 x float> @test_rootn_afn_v2f32__2(
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call afn <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]), !fpmath [[META0]]
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
entry:
%call = tail call afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> splat (i32 2))
ret <2 x float> %call
}
define <2 x float> @test_rootn_afn_v2f32__3(<2 x float> %x) #0 {
; CHECK-LABEL: define <2 x float> @test_rootn_afn_v2f32__3(
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2CBRT:%.*]] = call afn <2 x float> @_Z4cbrtDv2_f(<2 x float> [[X]])
; CHECK-NEXT: ret <2 x float> [[__ROOTN2CBRT]]
;
entry:
%call = tail call afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> splat (i32 3))
ret <2 x float> %call
}
define <2 x float> @test_rootn_afn_v2f32__neg1(<2 x float> %x) #0 {
; CHECK-LABEL: define <2 x float> @test_rootn_afn_v2f32__neg1(
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv afn <2 x float> splat (float 1.000000e+00), [[X]]
; CHECK-NEXT: ret <2 x float> [[__ROOTN2DIV]]
;
entry:
%call = tail call afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> splat (i32 -1))
ret <2 x float> %call
}
define <2 x float> @test_rootn_afn_v2f32__neg2(<2 x float> %x) #0 {
; CHECK-LABEL: define <2 x float> @test_rootn_afn_v2f32__neg2(
; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = call contract afn <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv contract afn <2 x float> splat (float 1.000000e+00), [[TMP0]], !fpmath [[META0]]
; CHECK-NEXT: ret <2 x float> [[TMP1]]
;
entry:
%call = tail call afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> splat (i32 -2))
ret <2 x float> %call
}
define float @test__rootn_fast_f32(float %x, i32 %y) #0 {
; CHECK-LABEL: define float @test__rootn_fast_f32(
; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z12__rootn_fastfi(float [[X]], i32 [[Y]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call float @_Z12__rootn_fastfi(float %x, i32 %y)
ret float %call
}
declare float @_Z12__rootn_fastfi(float, i32) #1
define <2 x float> @test__rootn_fast_v2f32(<2 x float> %x, <2 x i32> %y) #0 {
; CHECK-LABEL: define <2 x float> @test__rootn_fast_v2f32(
; CHECK-SAME: <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z12__rootn_fastDv2_fDv2_i(<2 x float> [[X]], <2 x i32> [[Y]])
; CHECK-NEXT: ret <2 x float> [[CALL]]
;
entry:
%call = tail call <2 x float> @_Z12__rootn_fastDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
ret <2 x float> %call
}
declare <2 x float> @_Z12__rootn_fastDv2_fDv2_i(<2 x float>, <2 x i32>) #1
define <3 x float> @test__rootn_fast_v3f32(<3 x float> %x, <3 x i32> %y) #0 {
; CHECK-LABEL: define <3 x float> @test__rootn_fast_v3f32(
; CHECK-SAME: <3 x float> [[X:%.*]], <3 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z12__rootn_fastDv3_fDv3_i(<3 x float> [[X]], <3 x i32> [[Y]])
; CHECK-NEXT: ret <3 x float> [[CALL]]
;
entry:
%call = tail call <3 x float> @_Z12__rootn_fastDv3_fDv3_i(<3 x float> %x, <3 x i32> %y)
ret <3 x float> %call
}
declare <3 x float> @_Z12__rootn_fastDv3_fDv3_i(<3 x float>, <3 x i32>) #1
define <4 x float> @test__rootn_fast_v4f32(<4 x float> %x, <4 x i32> %y) #0 {
; CHECK-LABEL: define <4 x float> @test__rootn_fast_v4f32(
; CHECK-SAME: <4 x float> [[X:%.*]], <4 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x float> @_Z12__rootn_fastDv4_fDv4_i(<4 x float> [[X]], <4 x i32> [[Y]])
; CHECK-NEXT: ret <4 x float> [[CALL]]
;
entry:
%call = tail call <4 x float> @_Z12__rootn_fastDv4_fDv4_i(<4 x float> %x, <4 x i32> %y)
ret <4 x float> %call
}
declare <4 x float> @_Z12__rootn_fastDv4_fDv4_i(<4 x float>, <4 x i32>) #1
define <8 x float> @test__rootn_fast_v8f32(<8 x float> %x, <8 x i32> %y) #0 {
; CHECK-LABEL: define <8 x float> @test__rootn_fast_v8f32(
; CHECK-SAME: <8 x float> [[X:%.*]], <8 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x float> @_Z12__rootn_fastDv8_fDv8_i(<8 x float> [[X]], <8 x i32> [[Y]])
; CHECK-NEXT: ret <8 x float> [[CALL]]
;
entry:
%call = tail call <8 x float> @_Z12__rootn_fastDv8_fDv8_i(<8 x float> %x, <8 x i32> %y)
ret <8 x float> %call
}
declare <8 x float> @_Z12__rootn_fastDv8_fDv8_i(<8 x float>, <8 x i32>) #1
define <16 x float> @test__rootn_fast_v16f32(<16 x float> %x, <16 x i32> %y) #0 {
; CHECK-LABEL: define <16 x float> @test__rootn_fast_v16f32(
; CHECK-SAME: <16 x float> [[X:%.*]], <16 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x float> @_Z12__rootn_fastDv16_fDv16_i(<16 x float> [[X]], <16 x i32> [[Y]])
; CHECK-NEXT: ret <16 x float> [[CALL]]
;
entry:
%call = tail call <16 x float> @_Z12__rootn_fastDv16_fDv16_i(<16 x float> %x, <16 x i32> %y)
ret <16 x float> %call
}
declare <16 x float> @_Z12__rootn_fastDv16_fDv16_i(<16 x float>, <16 x i32>) #1
define float @test__rootn_fast_f32__1(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_f32__1(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: ret float [[X]]
;
entry:
%call = tail call float @_Z12__rootn_fastfi(float %x, i32 1)
ret float %call
}
define float @test__rootn_fast_afn_f32__1(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_afn_f32__1(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: ret float [[X]]
;
entry:
%call = tail call afn float @_Z12__rootn_fastfi(float %x, i32 1)
ret float %call
}
define float @test__rootn_fast_f32__2(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_f32__2(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call float @_Z12__rootn_fastfi(float %x, i32 2)
ret float %call
}
define float @test__rootn_fast_afn_f32__2(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_afn_f32__2(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call afn float @llvm.sqrt.f32(float [[X]]), !fpmath [[META0]]
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = tail call afn float @_Z12__rootn_fastfi(float %x, i32 2)
ret float %call
}
define float @test__rootn_fast_f32__3(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_f32__3(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2CBRT:%.*]] = call float @_Z4cbrtf(float [[X]])
; CHECK-NEXT: ret float [[__ROOTN2CBRT]]
;
entry:
%call = tail call float @_Z12__rootn_fastfi(float %x, i32 3)
ret float %call
}
define float @test__rootn_fast_afn_f32__3(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_afn_f32__3(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2CBRT:%.*]] = call afn float @_Z4cbrtf(float [[X]])
; CHECK-NEXT: ret float [[__ROOTN2CBRT]]
;
entry:
%call = tail call afn float @_Z12__rootn_fastfi(float %x, i32 3)
ret float %call
}
define float @test__rootn_fast_f32__neg1(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_f32__neg1(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv float 1.000000e+00, [[X]]
; CHECK-NEXT: ret float [[__ROOTN2DIV]]
;
entry:
%call = tail call float @_Z12__rootn_fastfi(float %x, i32 -1)
ret float %call
}
define float @test__rootn_fast_afn_f32__neg1(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_afn_f32__neg1(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv afn float 1.000000e+00, [[X]]
; CHECK-NEXT: ret float [[__ROOTN2DIV]]
;
entry:
%call = tail call afn float @_Z12__rootn_fastfi(float %x, i32 -1)
ret float %call
}
define float @test__rootn_fast_f32__neg2(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_f32__neg2(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = call contract float @llvm.sqrt.f32(float [[X]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv contract float 1.000000e+00, [[TMP0]], !fpmath [[META0]]
; CHECK-NEXT: ret float [[TMP1]]
;
entry:
%call = tail call float @_Z12__rootn_fastfi(float %x, i32 -2)
ret float %call
}
define float @test__rootn_fast_afn_f32__neg2(float %x) #0 {
; CHECK-LABEL: define float @test__rootn_fast_afn_f32__neg2(
; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = call contract afn float @llvm.sqrt.f32(float [[X]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv contract afn float 1.000000e+00, [[TMP0]], !fpmath [[META0]]
; CHECK-NEXT: ret float [[TMP1]]
;
entry:
%call = tail call afn float @_Z12__rootn_fastfi(float %x, i32 -2)
ret float %call
}
define double @test_rootn_afn_f64(double %x, i32 %y) #0 {
; CHECK-LABEL: define double @test_rootn_afn_f64(
; CHECK-SAME: double [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn double @_Z5rootndi(double [[X]], i32 [[Y]])
; CHECK-NEXT: ret double [[CALL]]
;
entry:
%call = tail call afn double @_Z5rootndi(double %x, i32 %y)
ret double %call
}
declare double @_Z5rootndi(double, i32) #0
define <2 x double> @test_rootn_afn_v2f64(<2 x double> %x, <2 x i32> %y) #0 {
; CHECK-LABEL: define <2 x double> @test_rootn_afn_v2f64(
; CHECK-SAME: <2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <2 x double> @_Z5rootnDv2_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> @_Z5rootnDv2_dDv2_i(<2 x double> %x, <2 x i32> %y)
ret <2 x double> %call
}
declare <2 x double> @_Z5rootnDv2_dDv2_i(<2 x double>, <2 x i32>) #0
define half @test_rootn_f16(half noundef %x, i32 %y) #0 {
; CHECK-LABEL: define half @test_rootn_f16(
; CHECK-SAME: half noundef [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn half @_Z5rootnDhi(half [[X]], i32 [[Y]])
; CHECK-NEXT: ret half [[CALL]]
;
entry:
%call = tail call afn half @_Z5rootnDhi(half %x, i32 %y)
ret half %call
}
declare half @_Z5rootnDhi(half noundef, i32 noundef) #01
define <2 x half> @test_rootn_afn_v2f16(<2 x half> %x, <2 x i32> %y) #0 {
; CHECK-LABEL: define <2 x half> @test_rootn_afn_v2f16(
; CHECK-SAME: <2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = tail call afn <2 x half> @_Z5rootnDv2_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> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> %y)
ret <2 x half> %call
}
declare <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half>, <2 x i32>) #0
attributes #0 = { mustprogress nofree norecurse nounwind willreturn memory(none) }
attributes #1 = { mustprogress nofree nounwind willreturn memory(none) }
;.
; CHECK: [[META0]] = !{float 2.000000e+00}
;.