[llvm] 3c86bc0 - AMDGPU: Add more tests for rootn libcall handling

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 2 06:53:42 PST 2023


Author: Matt Arsenault
Date: 2023-12-02T21:53:31+07:00
New Revision: 3c86bc0ae9b3df289ca005d3c451512f01be6d61

URL: https://github.com/llvm/llvm-project/commit/3c86bc0ae9b3df289ca005d3c451512f01be6d61
DIFF: https://github.com/llvm/llvm-project/commit/3c86bc0ae9b3df289ca005d3c451512f01be6d61.diff

LOG: AMDGPU: Add more tests for rootn libcall handling

Added: 
    llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll
new file mode 100644
index 000000000000..421b2d88dcfe
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll
@@ -0,0 +1,1497 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-simplifylib,instcombine -amdgpu-prelink %s | FileCheck %s
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8"
+
+declare float @_Z5rootnfi(float, i32)
+declare <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float>, <2 x i32>)
+declare <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float>, <3 x i32>)
+declare <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float>, <4 x i32>)
+declare <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float>, <8 x i32>)
+declare <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float>, <16 x i32>)
+declare double @_Z5rootndi(double, i32)
+declare <2 x double> @_Z5rootnDv2_dDv2_i(<2 x double>, <2 x i32>)
+declare <3 x double> @_Z5rootnDv3_dDv3_i(<3 x double>, <3 x i32>)
+declare <4 x double> @_Z5rootnDv4_dDv4_i(<4 x double>, <4 x i32>)
+declare <8 x double> @_Z5rootnDv8_dDv8_i(<8 x double>, <8 x i32>)
+declare <16 x double> @_Z5rootnDv16_dDv16_i(<16 x double>, <16 x i32>)
+declare half @_Z5rootnDhi(half, i32)
+declare <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half>, <2 x i32>)
+declare <3 x half> @_Z5rootnDv3_DhDv3_i(<3 x half>, <3 x i32>)
+declare <4 x half> @_Z5rootnDv4_DhDv4_i(<4 x half>, <4 x i32>)
+declare <8 x half> @_Z5rootnDv8_DhDv8_i(<8 x half>, <8 x i32>)
+declare <16 x half> @_Z5rootnDv16_DhDv16_i(<16 x half>, <16 x i32>)
+
+define float @test_rootn_f32(float %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_f32(
+; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_rootn_f32_flags(float %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_f32_flags(
+; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan nsz float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call nnan nsz float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32(<2 x float> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
+  ret <2 x float> %call
+}
+
+define <3 x float> @test_rootn_v3f32(<3 x float> %x, <3 x i32> %y) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32(
+; CHECK-SAME: <3 x float> [[X:%.*]], <3 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> [[Y]])
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> %y)
+  ret <3 x float> %call
+}
+
+define <4 x float> @test_rootn_v4f32(<4 x float> %x, <4 x i32> %y) {
+; CHECK-LABEL: define <4 x float> @test_rootn_v4f32(
+; CHECK-SAME: <4 x float> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> [[Y]])
+; CHECK-NEXT:    ret <4 x float> [[CALL]]
+;
+entry:
+  %call = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> %x, <4 x i32> %y)
+  ret <4 x float> %call
+}
+
+define <8 x float> @test_rootn_v8f32(<8 x float> %x, <8 x i32> %y) {
+; CHECK-LABEL: define <8 x float> @test_rootn_v8f32(
+; CHECK-SAME: <8 x float> [[X:%.*]], <8 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> [[X]], <8 x i32> [[Y]])
+; CHECK-NEXT:    ret <8 x float> [[CALL]]
+;
+entry:
+  %call = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> %x, <8 x i32> %y)
+  ret <8 x float> %call
+}
+
+define <16 x float> @test_rootn_v16f32(<16 x float> %x, <16 x i32> %y) {
+; CHECK-LABEL: define <16 x float> @test_rootn_v16f32(
+; CHECK-SAME: <16 x float> [[X:%.*]], <16 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> [[X]], <16 x i32> [[Y]])
+; CHECK-NEXT:    ret <16 x float> [[CALL]]
+;
+entry:
+  %call = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> %x, <16 x i32> %y)
+  ret <16 x float> %call
+}
+
+define double @test_rootn_f64(double %x, i32 %y) {
+; CHECK-LABEL: define double @test_rootn_f64(
+; CHECK-SAME: double [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call double @_Z5rootndi(double [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret double [[CALL]]
+;
+entry:
+  %call = tail call double @_Z5rootndi(double %x, i32 %y)
+  ret double %call
+}
+
+define <2 x double> @test_rootn_v2f64(<2 x double> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x double> @test_rootn_v2f64(
+; CHECK-SAME: <2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <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 <2 x double> @_Z5rootnDv2_dDv2_i(<2 x double> %x, <2 x i32> %y)
+  ret <2 x double> %call
+}
+
+define <3 x double> @test_rootn_v3f64(<3 x double> %x, <3 x i32> %y) {
+; CHECK-LABEL: define <3 x double> @test_rootn_v3f64(
+; CHECK-SAME: <3 x double> [[X:%.*]], <3 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x double> @_Z5rootnDv3_dDv3_i(<3 x double> [[X]], <3 x i32> [[Y]])
+; CHECK-NEXT:    ret <3 x double> [[CALL]]
+;
+entry:
+  %call = tail call <3 x double> @_Z5rootnDv3_dDv3_i(<3 x double> %x, <3 x i32> %y)
+  ret <3 x double> %call
+}
+
+define <4 x double> @test_rootn_v4f64(<4 x double> %x, <4 x i32> %y) {
+; CHECK-LABEL: define <4 x double> @test_rootn_v4f64(
+; CHECK-SAME: <4 x double> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x double> @_Z5rootnDv4_dDv4_i(<4 x double> [[X]], <4 x i32> [[Y]])
+; CHECK-NEXT:    ret <4 x double> [[CALL]]
+;
+entry:
+  %call = tail call <4 x double> @_Z5rootnDv4_dDv4_i(<4 x double> %x, <4 x i32> %y)
+  ret <4 x double> %call
+}
+
+define <8 x double> @test_rootn_v8f64(<8 x double> %x, <8 x i32> %y) {
+; CHECK-LABEL: define <8 x double> @test_rootn_v8f64(
+; CHECK-SAME: <8 x double> [[X:%.*]], <8 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x double> @_Z5rootnDv8_dDv8_i(<8 x double> [[X]], <8 x i32> [[Y]])
+; CHECK-NEXT:    ret <8 x double> [[CALL]]
+;
+entry:
+  %call = tail call <8 x double> @_Z5rootnDv8_dDv8_i(<8 x double> %x, <8 x i32> %y)
+  ret <8 x double> %call
+}
+
+define <16 x double> @test_rootn_v16f64(<16 x double> %x, <16 x i32> %y) {
+; CHECK-LABEL: define <16 x double> @test_rootn_v16f64(
+; CHECK-SAME: <16 x double> [[X:%.*]], <16 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x double> @_Z5rootnDv16_dDv16_i(<16 x double> [[X]], <16 x i32> [[Y]])
+; CHECK-NEXT:    ret <16 x double> [[CALL]]
+;
+entry:
+  %call = tail call <16 x double> @_Z5rootnDv16_dDv16_i(<16 x double> %x, <16 x i32> %y)
+  ret <16 x double> %call
+}
+
+define half @test_rootn_f16(half %x, i32 %y) {
+; CHECK-LABEL: define half @test_rootn_f16(
+; CHECK-SAME: half [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call half @_Z5rootnDhi(half [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret half [[CALL]]
+;
+entry:
+  %call = tail call half @_Z5rootnDhi(half %x, i32 %y)
+  ret half %call
+}
+
+define <2 x half> @test_rootn_v2f16(<2 x half> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16(
+; CHECK-SAME: <2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <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 <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> %y)
+  ret <2 x half> %call
+}
+
+define <3 x half> @test_rootn_v3f16(<3 x half> %x, <3 x i32> %y) {
+; CHECK-LABEL: define <3 x half> @test_rootn_v3f16(
+; CHECK-SAME: <3 x half> [[X:%.*]], <3 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x half> @_Z5rootnDv3_DhDv3_i(<3 x half> [[X]], <3 x i32> [[Y]])
+; CHECK-NEXT:    ret <3 x half> [[CALL]]
+;
+entry:
+  %call = tail call <3 x half> @_Z5rootnDv3_DhDv3_i(<3 x half> %x, <3 x i32> %y)
+  ret <3 x half> %call
+}
+
+define <4 x half> @test_rootn_v4f16(<4 x half> %x, <4 x i32> %y) {
+; CHECK-LABEL: define <4 x half> @test_rootn_v4f16(
+; CHECK-SAME: <4 x half> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x half> @_Z5rootnDv4_DhDv4_i(<4 x half> [[X]], <4 x i32> [[Y]])
+; CHECK-NEXT:    ret <4 x half> [[CALL]]
+;
+entry:
+  %call = tail call <4 x half> @_Z5rootnDv4_DhDv4_i(<4 x half> %x, <4 x i32> %y)
+  ret <4 x half> %call
+}
+
+define <8 x half> @test_rootn_v8f16(<8 x half> %x, <8 x i32> %y) {
+; CHECK-LABEL: define <8 x half> @test_rootn_v8f16(
+; CHECK-SAME: <8 x half> [[X:%.*]], <8 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x half> @_Z5rootnDv8_DhDv8_i(<8 x half> [[X]], <8 x i32> [[Y]])
+; CHECK-NEXT:    ret <8 x half> [[CALL]]
+;
+entry:
+  %call = tail call <8 x half> @_Z5rootnDv8_DhDv8_i(<8 x half> %x, <8 x i32> %y)
+  ret <8 x half> %call
+}
+
+define <16 x half> @test_rootn_v16f16(<16 x half> %x, <16 x i32> %y) {
+; CHECK-LABEL: define <16 x half> @test_rootn_v16f16(
+; CHECK-SAME: <16 x half> [[X:%.*]], <16 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x half> @_Z5rootnDv16_DhDv16_i(<16 x half> [[X]], <16 x i32> [[Y]])
+; CHECK-NEXT:    ret <16 x half> [[CALL]]
+;
+entry:
+  %call = tail call <16 x half> @_Z5rootnDv16_DhDv16_i(<16 x half> %x, <16 x i32> %y)
+  ret <16 x half> %call
+}
+
+define half @test_rootn_f16_0(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_0(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call half @_Z5rootnDhi(half [[X]], i32 0)
+; CHECK-NEXT:    ret half [[CALL]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 0)
+  ret half %call
+}
+
+define half @test_rootn_f16_1(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_1(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    ret half [[X]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 1)
+  ret half %call
+}
+
+define half @test_rootn_f16_2(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_2(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[__ROOTN2SQRT:%.*]] = call half @_Z4sqrtDh(half [[X]])
+; CHECK-NEXT:    ret half [[__ROOTN2SQRT]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 2)
+  ret half %call
+}
+
+define half @test_rootn_f16_3(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_3(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[__ROOTN2CBRT:%.*]] = call half @_Z4cbrtDh(half [[X]])
+; CHECK-NEXT:    ret half [[__ROOTN2CBRT]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 3)
+  ret half %call
+}
+
+define half @test_rootn_f16_neg1(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_neg1(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[__ROOTN2DIV:%.*]] = fdiv half 0xH3C00, [[X]]
+; CHECK-NEXT:    ret half [[__ROOTN2DIV]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 -1)
+  ret half %call
+}
+
+define half @test_rootn_f16_neg2(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_neg2(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[__ROOTN2RSQRT:%.*]] = call half @_Z5rsqrtDh(half [[X]])
+; CHECK-NEXT:    ret half [[__ROOTN2RSQRT]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 -2)
+  ret half %call
+}
+
+define half @test_rootn_f16_neg3(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_neg3(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call half @_Z5rootnDhi(half [[X]], i32 -3)
+; CHECK-NEXT:    ret half [[CALL]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 -3)
+  ret half %call
+}
+
+define half @test_rootn_f16_neg4(half %x) {
+; CHECK-LABEL: define half @test_rootn_f16_neg4(
+; CHECK-SAME: half [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call half @_Z5rootnDhi(half [[X]], i32 -4)
+; CHECK-NEXT:    ret half [[CALL]]
+;
+  %call = tail call half @_Z5rootnDhi(half %x, i32 -4)
+  ret half %call
+}
+
+define <2 x half> @test_rootn_v2f16_0(<2 x half> %x) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_0(
+; CHECK-SAME: <2 x half> [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> zeroinitializer)
+; CHECK-NEXT:    ret <2 x half> [[CALL]]
+;
+  %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> zeroinitializer)
+  ret <2 x half> %call
+}
+
+define <2 x half> @test_rootn_v2f16_1(<2 x half> %x) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_1(
+; CHECK-SAME: <2 x half> [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> <i32 1, i32 1>)
+; CHECK-NEXT:    ret <2 x half> [[CALL]]
+;
+  %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> <i32 1, i32 1>)
+  ret <2 x half> %call
+}
+
+define <2 x half> @test_rootn_v2f16_2(<2 x half> %x) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_2(
+; CHECK-SAME: <2 x half> [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> <i32 2, i32 2>)
+; CHECK-NEXT:    ret <2 x half> [[CALL]]
+;
+  %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> <i32 2, i32 2>)
+  ret <2 x half> %call
+}
+
+define <2 x half> @test_rootn_v2f16_neg1(<2 x half> %x) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_neg1(
+; CHECK-SAME: <2 x half> [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> <i32 -1, i32 -1>)
+; CHECK-NEXT:    ret <2 x half> [[CALL]]
+;
+  %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> <i32 -1, i32 -1>)
+  ret <2 x half> %call
+}
+
+define <2 x half> @test_rootn_v2f16_neg2(<2 x half> %x) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_neg2(
+; CHECK-SAME: <2 x half> [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> <i32 -2, i32 -2>)
+; CHECK-NEXT:    ret <2 x half> [[CALL]]
+;
+  %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> <i32 -2, i32 -2>)
+  ret <2 x half> %call
+}
+
+define <2 x half> @test_rootn_v2f16_neg3(<2 x half> %x) {
+; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_neg3(
+; CHECK-SAME: <2 x half> [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> <i32 -3, i32 -3>)
+; CHECK-NEXT:    ret <2 x half> [[CALL]]
+;
+  %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> <i32 -3, i32 -3>)
+  ret <2 x half> %call
+}
+
+define float @test_rootn_f32__y_0(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_0(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 0)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 0)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_poison(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_poison(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 poison)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 poison)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_poison(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_poison(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> poison)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> poison)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_0(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_0(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> zeroinitializer)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> zeroinitializer)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_0_undef(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_0_undef(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 0, i32 poison>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 0, i32 poison>)
+  ret <2 x float> %call
+}
+
+define <3 x float> @test_rootn_v3f32__y_0(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_0(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> zeroinitializer)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> zeroinitializer)
+  ret <3 x float> %call
+}
+
+define <4 x float> @test_rootn_v4f32__y_0(<4 x float> %x) {
+; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_0(
+; CHECK-SAME: <4 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> zeroinitializer)
+; CHECK-NEXT:    ret <4 x float> [[CALL]]
+;
+entry:
+  %call = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> %x, <4 x i32> zeroinitializer)
+  ret <4 x float> %call
+}
+
+define <8 x float> @test_rootn_v8f32__y_0(<8 x float> %x) {
+; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_0(
+; CHECK-SAME: <8 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> [[X]], <8 x i32> zeroinitializer)
+; CHECK-NEXT:    ret <8 x float> [[CALL]]
+;
+entry:
+  %call = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> %x, <8 x i32> zeroinitializer)
+  ret <8 x float> %call
+}
+
+define <16 x float> @test_rootn_v16f32__y_0(<16 x float> %x) {
+; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_0(
+; CHECK-SAME: <16 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> [[X]], <16 x i32> zeroinitializer)
+; CHECK-NEXT:    ret <16 x float> [[CALL]]
+;
+entry:
+  %call = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> %x, <16 x i32> zeroinitializer)
+  ret <16 x float> %call
+}
+
+define float @test_rootn_f32__y_1(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_1(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret float [[X]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 1)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_1__strictfp(float %x) #1 {
+; CHECK-LABEL: define float @test_rootn_f32__y_1__strictfp(
+; CHECK-SAME: float [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret float [[X]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 1) #1
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_1(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 1, i32 1>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 1, i32 1>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_1__strictfp(<2 x float> %x) #1 {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1__strictfp(
+; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 1, i32 1>) #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 1, i32 1>) #1
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_1_undef(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1_undef(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 1, i32 poison>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 1, i32 poison>)
+  ret <2 x float> %call
+}
+
+define <3 x float> @test_rootn_v3f32__y_1(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_1(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> <i32 1, i32 1, i32 1>)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_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_rootn_v3f32__y_1_undef(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_1_undef(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> <i32 1, i32 1, i32 poison>)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_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_rootn_v4f32__y_1(<4 x float> %x) {
+; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_1(
+; CHECK-SAME: <4 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
+; CHECK-NEXT:    ret <4 x float> [[CALL]]
+;
+entry:
+  %call = tail call <4 x float> @_Z5rootnDv4_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_rootn_v8f32__y_1(<8 x float> %x) {
+; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_1(
+; CHECK-SAME: <8 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_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>)
+; CHECK-NEXT:    ret <8 x float> [[CALL]]
+;
+entry:
+  %call = tail call <8 x float> @_Z5rootnDv8_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_rootn_v16f32__y_1(<16 x float> %x) {
+; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_1(
+; CHECK-SAME: <16 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_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>)
+; CHECK-NEXT:    ret <16 x float> [[CALL]]
+;
+entry:
+  %call = tail call <16 x float> @_Z5rootnDv16_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_rootn_f32__y_2(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2SQRT:%.*]] = call float @_Z4sqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2SQRT]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 2)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_2_flags(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_2_flags(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2SQRT:%.*]] = call nnan nsz float @_Z4sqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2SQRT]]
+;
+entry:
+  %call = tail call nnan nsz float @_Z5rootnfi(float %x, i32 2)
+  ret float %call
+}
+
+; Should retain looser existing !fpmath requirements.
+define float @test_rootn_f32__y_2_fpmath_3(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_2_fpmath_3(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2SQRT:%.*]] = call nnan nsz float @_Z4sqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2SQRT]]
+;
+entry:
+  %call = tail call nnan nsz float @_Z5rootnfi(float %x, i32 2), !fpmath !0
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_2_flags(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_2_flags(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan nsz <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 2, i32 2>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call nnan nsz <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 2, i32 2>)
+  ret <2 x float> %call
+}
+
+define <3 x float> @test_rootn_v3f32__y_2(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_2(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> <i32 2, i32 2, i32 2>)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_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_rootn_v3f32__y_2_undef(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_2_undef(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> <i32 2, i32 poison, i32 2>)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_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_rootn_v4f32__y_2(<4 x float> %x) {
+; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_2(
+; CHECK-SAME: <4 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> <i32 2, i32 2, i32 2, i32 2>)
+; CHECK-NEXT:    ret <4 x float> [[CALL]]
+;
+entry:
+  %call = tail call <4 x float> @_Z5rootnDv4_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_rootn_v8f32__y_2(<8 x float> %x) {
+; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_2(
+; CHECK-SAME: <8 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_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>)
+; CHECK-NEXT:    ret <8 x float> [[CALL]]
+;
+entry:
+  %call = tail call <8 x float> @_Z5rootnDv8_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_rootn_v16f32__y_2(<16 x float> %x) {
+; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_2(
+; CHECK-SAME: <16 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_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>)
+; CHECK-NEXT:    ret <16 x float> [[CALL]]
+;
+entry:
+  %call = tail call <16 x float> @_Z5rootnDv16_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_rootn_f32__y_3(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_3(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2CBRT:%.*]] = call float @_Z4cbrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2CBRT]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 3)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_3(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_3(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 3, i32 3>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 3, i32 3>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_nonsplat_2_3(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_nonsplat_2_3(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 2, i32 3>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 2, i32 3>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_nonsplat_2_poison(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_nonsplat_2_poison(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 2, i32 poison>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 2, i32 poison>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_nonsplat_2_5(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_nonsplat_2_5(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 2, i32 5>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 2, i32 5>)
+  ret <2 x float> %call
+}
+
+define float @test_rootn_f32__y_neg1(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg1(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2DIV:%.*]] = fdiv float 1.000000e+00, [[X]]
+; CHECK-NEXT:    ret float [[__ROOTN2DIV]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 -1)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_neg1(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg1(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 -1, i32 -1>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -1, i32 -1>)
+  ret <2 x float> %call
+}
+
+define <3 x float> @test_rootn_v3f32__y_neg1(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_neg1(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> <i32 -1, i32 -1, i32 -1>)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_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_rootn_v3f32__y_neg1_undef(<3 x float> %x) {
+; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_neg1_undef(
+; CHECK-SAME: <3 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> <i32 -1, i32 -1, i32 poison>)
+; CHECK-NEXT:    ret <3 x float> [[CALL]]
+;
+entry:
+  %call = tail call <3 x float> @_Z5rootnDv3_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_rootn_v4f32__y_neg1(<4 x float> %x) {
+; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_neg1(
+; CHECK-SAME: <4 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
+; CHECK-NEXT:    ret <4 x float> [[CALL]]
+;
+entry:
+  %call = tail call <4 x float> @_Z5rootnDv4_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_rootn_v8f32__y_neg1(<8 x float> %x) {
+; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_neg1(
+; CHECK-SAME: <8 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_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>)
+; CHECK-NEXT:    ret <8 x float> [[CALL]]
+;
+entry:
+  %call = tail call <8 x float> @_Z5rootnDv8_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_rootn_v16f32__y_neg1(<16 x float> %x) {
+; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_neg1(
+; CHECK-SAME: <16 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_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>)
+; CHECK-NEXT:    ret <16 x float> [[CALL]]
+;
+entry:
+  %call = tail call <16 x float> @_Z5rootnDv16_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_rootn_f32__y_neg2(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg2(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2RSQRT]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 -2)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg2__flags(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg2__flags(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2RSQRT:%.*]] = call nnan nsz float @_Z5rsqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2RSQRT]]
+;
+entry:
+  %call = tail call nsz nnan float @_Z5rootnfi(float %x, i32 -2)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg2__strictfp(float %x) #1 {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg2__strictfp(
+; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2RSQRT]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 -2) #1
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg2__noinline(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg2__noinline(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2RSQRT]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 -2) #2
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg2__nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg2__nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 -2) #0
+  ret float %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_neg2(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 -2, i32 -2>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -2, i32 -2>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_neg2__flags(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2__flags(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan nsz <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 -2, i32 -2>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call nsz nnan <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -2, i32 -2>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_v2f32__y_neg2__strictfp(<2 x float> %x) #1 {
+; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2__strictfp(
+; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 -2, i32 -2>) #[[ATTR0]]
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -2, i32 -2>) #1
+  ret <2 x float> %call
+}
+
+define float @test_rootn_f32__y_neg3(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg3(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -3)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 -3)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg4(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg4(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -4)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 -4)
+  ret float %call
+}
+
+define float @test_rootn_afn_f32(float %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_afn_f32(
+; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call afn float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call afn float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_afn_v2f32(<2 x float> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_v2f32(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call afn <2 x float> @_Z5rootnDv2_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
+}
+
+define double @test_rootn_afn_f64(double %x, i32 %y) {
+; CHECK-LABEL: define double @test_rootn_afn_f64(
+; CHECK-SAME: double [[X:%.*]], i32 [[Y:%.*]]) {
+; 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
+}
+
+define <2 x double> @test_rootn_afn_v2f64(<2 x double> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x double> @test_rootn_afn_v2f64(
+; CHECK-SAME: <2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; 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
+}
+
+define half @test_rootn_afn_f16(half %x, i32 %y) {
+; CHECK-LABEL: define half @test_rootn_afn_f16(
+; CHECK-SAME: half [[X:%.*]], i32 [[Y:%.*]]) {
+; 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
+}
+
+define <2 x half> @test_rootn_afn_v2f16(<2 x half> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x half> @test_rootn_afn_v2f16(
+; CHECK-SAME: <2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; 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
+}
+
+define float @test_rootn_afn_nnan_ninf_f32(float %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32(
+; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> %y)
+  ret <2 x float> %call
+}
+
+define double @test_rootn_afn_nnan_ninf_f64(double %x, i32 %y) {
+; CHECK-LABEL: define double @test_rootn_afn_nnan_ninf_f64(
+; CHECK-SAME: double [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn double @_Z5rootndi(double [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret double [[CALL]]
+;
+entry:
+  %call = tail call nnan ninf afn double @_Z5rootndi(double %x, i32 %y)
+  ret double %call
+}
+
+define <2 x double> @test_rootn_afn_nnan_ninf_v2f64(<2 x double> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x double> @test_rootn_afn_nnan_ninf_v2f64(
+; CHECK-SAME: <2 x double> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf 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 nnan ninf afn <2 x double> @_Z5rootnDv2_dDv2_i(<2 x double> %x, <2 x i32> %y)
+  ret <2 x double> %call
+}
+
+define half @test_rootn_afn_nnan_ninf_f16(half %x, i32 %y) {
+; CHECK-LABEL: define half @test_rootn_afn_nnan_ninf_f16(
+; CHECK-SAME: half [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn half @_Z5rootnDhi(half [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret half [[CALL]]
+;
+entry:
+  %call = tail call nnan ninf afn half @_Z5rootnDhi(half %x, i32 %y)
+  ret half %call
+}
+
+define <2 x half> @test_rootn_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x half> @test_rootn_afn_nnan_ninf_v2f16(
+; CHECK-SAME: <2 x half> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf 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 nnan ninf afn <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> %y)
+  ret <2 x half> %call
+}
+
+define float @test_rootn_fast_f32_nobuiltin(float %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_fast_f32_nobuiltin(
+; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call fast float @_Z5rootnfi(float [[X]], i32 [[Y]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call fast float @_Z5rootnfi(float %x, i32 %y) #0
+  ret float %call
+}
+
+define float @test_rootn_fast_f32_strictfp(float %x, i32 %y) #1 {
+; CHECK-LABEL: define float @test_rootn_fast_f32_strictfp(
+; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call fast float @_Z5rootnfi(float [[X]], i32 [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call fast float @_Z5rootnfi(float %x, i32 %y) #1
+  ret float %call
+}
+
+define float @test_rootn_fast_f32__y_poison(float %x) {
+; CHECK-LABEL: define float @test_rootn_fast_f32__y_poison(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call fast float @_Z5rootnfi(float [[X]], i32 poison)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call fast float @_Z5rootnfi(float %x, i32 poison)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_3(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_3(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[__ROOTN2CBRT:%.*]] = call nnan ninf afn float @_Z4cbrtf(float [[X]])
+; CHECK-NEXT:    ret float [[__ROOTN2CBRT]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 3)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_neg3(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_neg3(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 -3)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 -3)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_4(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_4(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 4)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 4)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_neg4(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_neg4(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 -4)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 -4)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_5(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_5(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 5)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 5)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_neg5(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_neg5(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 -5)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 -5)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_7(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_7(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 7)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 7)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_neg7(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_neg7(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 -7)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 -7)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_8(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_8(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 8)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 8)
+  ret float %call
+}
+
+define float @test_rootn_afn_nnan_ninf_f32__y_neg8(float %x) {
+; CHECK-LABEL: define float @test_rootn_afn_nnan_ninf_f32__y_neg8(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 -8)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call nnan ninf afn float @_Z5rootnfi(float %x, i32 -8)
+  ret float %call
+}
+
+define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_3(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_3(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 3, i32 3>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call afn nnan ninf <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 3, i32 3>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_4(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_4(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 4, i32 4>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call afn nnan ninf <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 4, i32 4>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_neg3(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_neg3(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 -3, i32 -3>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call afn nnan ninf <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -3, i32 -3>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_neg4(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_neg4(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 -4, i32 -4>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call afn nnan ninf <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 -4, i32 -4>)
+  ret <2 x float> %call
+}
+
+define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_5(<2 x float> %x) {
+; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_5(
+; CHECK-SAME: <2 x float> [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> <i32 5, i32 5>)
+; CHECK-NEXT:    ret <2 x float> [[CALL]]
+;
+entry:
+  %call = tail call afn nnan ninf <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> <i32 5, i32 5>)
+  ret <2 x float> %call
+}
+
+define float @test_rootn_f32__x_known_positive(float nofpclass(ninf nsub nnorm) %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_f32__x_known_positive(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_rootn_afn_f32__x_known_positive(float nofpclass(ninf nsub nnorm) %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_afn_f32__x_known_positive(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call afn float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call afn float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_rootn_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf nsub nnorm) %x, i32 %y) {
+; CHECK-LABEL: define float @test_rootn_afn_ninf_nnan_f32__x_known_positive(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call nnan ninf afn float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call afn ninf nnan float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_rootn_afn_f32__x_known_positive__y_4(float nofpclass(ninf nsub nnorm) %x) {
+; CHECK-LABEL: define float @test_rootn_afn_f32__x_known_positive__y_4(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call afn float @_Z5rootnfi(float [[X]], i32 4)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call afn float @_Z5rootnfi(float %x, i32 4)
+  ret float %call
+}
+
+define float @test_rootn_f32__x_known_positive__y_4(float nofpclass(ninf nsub nnorm) %x) {
+; CHECK-LABEL: define float @test_rootn_f32__x_known_positive__y_4(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 4)
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %call = tail call float @_Z5rootnfi(float %x, i32 4)
+  ret float %call
+}
+
+define float @test_rootn_f32_y_known_even(float %x, i32 %y.arg) {
+; CHECK-LABEL: define float @test_rootn_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 @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %y = shl i32 %y.arg, 1
+  %call = tail call float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_fast_rootn_f32_y_known_even(float %x, i32 %y.arg) {
+; CHECK-LABEL: define float @test_fast_rootn_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 fast float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %y = shl i32 %y.arg, 1
+  %call = tail call fast float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_fast_rootn_f32_known_positive_y_known_even(float nofpclass(ninf nsub nnorm) %x, i32 %y.arg) {
+; CHECK-LABEL: define float @test_fast_rootn_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:    [[CALL:%.*]] = tail call fast float @_Z5rootnfi(float [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret float [[CALL]]
+;
+entry:
+  %y = shl i32 %y.arg, 1
+  %call = tail call fast float @_Z5rootnfi(float %x, i32 %y)
+  ret float %call
+}
+
+define float @test_rootn_f32__y_0_nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_0_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 0) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 0) #0
+  ret float %call
+}
+
+define float @test_rootn_f32__y_1_nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_1_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 1) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 1) #0
+  ret float %call
+}
+
+define float @test_rootn_f32__y_2_nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_2_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 2) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 2) #0
+  ret float %call
+}
+
+define float @test_rootn_f32__y_3_nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_3_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 3) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 3) #0
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg1_nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg1_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -1) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 -1) #0
+  ret float %call
+}
+
+define float @test_rootn_f32__y_neg2_nobuiltin(float %x) {
+; CHECK-LABEL: define float @test_rootn_f32__y_neg2_nobuiltin(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT:    [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = tail call float @_Z5rootnfi(float %x, i32 -2) #0
+  ret float %call
+}
+
+attributes #0 = { nobuiltin }
+attributes #1 = { strictfp }
+attributes #2 = { noinline }
+
+
+!0 = !{float 3.0}
+;.
+; CHECK: attributes #[[ATTR0]] = { strictfp }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(read) }
+; CHECK: attributes #[[ATTR2]] = { nobuiltin }
+;.


        


More information about the llvm-commits mailing list