[llvm] r264944 - AMDGPU: Add frexp_exp intrinsic

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 30 15:28:53 PDT 2016


Author: arsenm
Date: Wed Mar 30 17:28:52 2016
New Revision: 264944

URL: http://llvm.org/viewvc/llvm-project?rev=264944&view=rev
Log:
AMDGPU: Add frexp_exp intrinsic

Added:
    llvm/trunk/test/CodeGen/AMDGPU/llvm.amdgcn.frexp.exp.ll
Modified:
    llvm/trunk/include/llvm/IR/IntrinsicsAMDGPU.td
    llvm/trunk/lib/Target/AMDGPU/SIInstructions.td
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/trunk/test/Transforms/InstCombine/amdgcn-intrinsics.ll

Modified: llvm/trunk/include/llvm/IR/IntrinsicsAMDGPU.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicsAMDGPU.td?rev=264944&r1=264943&r2=264944&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IntrinsicsAMDGPU.td (original)
+++ llvm/trunk/include/llvm/IR/IntrinsicsAMDGPU.td Wed Mar 30 17:28:52 2016
@@ -123,6 +123,10 @@ def int_amdgcn_frexp_mant : Intrinsic<
   [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
 >;
 
+def int_amdgcn_frexp_exp : Intrinsic<
+  [llvm_i32_ty], [llvm_anyfloat_ty], [IntrNoMem]
+>;
+
 def int_amdgcn_class : Intrinsic<
   [llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]
 >;

Modified: llvm/trunk/lib/Target/AMDGPU/SIInstructions.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/SIInstructions.td?rev=264944&r1=264943&r2=264944&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AMDGPU/SIInstructions.td (original)
+++ llvm/trunk/lib/Target/AMDGPU/SIInstructions.td Wed Mar 30 17:28:52 2016
@@ -1344,7 +1344,7 @@ defm V_FFBH_U32 : VOP1Inst <vop1<0x39, 0
 defm V_FFBL_B32 : VOP1Inst <vop1<0x3a, 0x2e>, "v_ffbl_b32", VOP_I32_I32>;
 defm V_FFBH_I32 : VOP1Inst <vop1<0x3b, 0x2f>, "v_ffbh_i32", VOP_I32_I32>;
 defm V_FREXP_EXP_I32_F64 : VOP1Inst <vop1<0x3c,0x30>, "v_frexp_exp_i32_f64",
-  VOP_I32_F64
+  VOP_I32_F64, int_amdgcn_frexp_exp
 >;
 
 let SchedRW = [WriteDoubleAdd] in {
@@ -1359,7 +1359,7 @@ defm V_FRACT_F64 : VOP1Inst <vop1<0x3e,
 
 
 defm V_FREXP_EXP_I32_F32 : VOP1Inst <vop1<0x3f, 0x33>, "v_frexp_exp_i32_f32",
-  VOP_I32_F32
+  VOP_I32_F32, int_amdgcn_frexp_exp
 >;
 defm V_FREXP_MANT_F32 : VOP1Inst <vop1<0x40, 0x34>, "v_frexp_mant_f32",
   VOP_F32_F32, int_amdgcn_frexp_mant

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=264944&r1=264943&r2=264944&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Wed Mar 30 17:28:52 2016
@@ -1846,17 +1846,28 @@ Instruction *InstCombiner::visitCallInst
 
     break;
   }
-  case Intrinsic::amdgcn_frexp_mant: {
+  case Intrinsic::amdgcn_frexp_mant:
+  case Intrinsic::amdgcn_frexp_exp: {
     Value *Src = II->getArgOperand(0);
     if (const ConstantFP *C = dyn_cast<ConstantFP>(Src)) {
       int Exp;
       APFloat Significand = frexp(C->getValueAPF(), Exp,
                                   APFloat::rmNearestTiesToEven);
 
-      return replaceInstUsesWith(CI, ConstantFP::get(II->getContext(),
-                                                     Significand));
-    } else if (isa<UndefValue>(Src))
-      return replaceInstUsesWith(CI, Src);
+      if (II->getIntrinsicID() == Intrinsic::amdgcn_frexp_mant) {
+        return replaceInstUsesWith(CI, ConstantFP::get(II->getContext(),
+                                                       Significand));
+      }
+
+      // Match instruction special case behavior.
+      if (Exp == APFloat::IEK_NaN || Exp == APFloat::IEK_Inf)
+        Exp = 0;
+
+      return replaceInstUsesWith(CI, ConstantInt::get(II->getType(), Exp));
+    }
+
+    if (isa<UndefValue>(Src))
+      return replaceInstUsesWith(CI, UndefValue::get(II->getType()));
 
     break;
   }

Added: llvm/trunk/test/CodeGen/AMDGPU/llvm.amdgcn.frexp.exp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AMDGPU/llvm.amdgcn.frexp.exp.ll?rev=264944&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AMDGPU/llvm.amdgcn.frexp.exp.ll (added)
+++ llvm/trunk/test/CodeGen/AMDGPU/llvm.amdgcn.frexp.exp.ll Wed Mar 30 17:28:52 2016
@@ -0,0 +1,64 @@
+; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
+; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s  | FileCheck -check-prefix=GCN %s
+
+declare float @llvm.fabs.f32(float) #0
+declare double @llvm.fabs.f64(double) #0
+declare i32 @llvm.amdgcn.frexp.exp.f32(float) #0
+declare i32 @llvm.amdgcn.frexp.exp.f64(double) #0
+
+; GCN-LABEL: {{^}}s_test_frexp_exp_f32:
+; GCN: v_frexp_exp_i32_f32_e32 {{v[0-9]+}}, {{s[0-9]+}}
+define void @s_test_frexp_exp_f32(i32 addrspace(1)* %out, float %src) #1 {
+  %frexp.exp = call i32 @llvm.amdgcn.frexp.exp.f32(float %src)
+  store i32 %frexp.exp, i32 addrspace(1)* %out
+  ret void
+}
+
+; GCN-LABEL: {{^}}s_test_fabs_frexp_exp_f32:
+; GCN: v_frexp_exp_i32_f32_e64 {{v[0-9]+}}, |{{s[0-9]+}}|
+define void @s_test_fabs_frexp_exp_f32(i32 addrspace(1)* %out, float %src) #1 {
+  %fabs.src = call float @llvm.fabs.f32(float %src)
+  %frexp.exp = call i32 @llvm.amdgcn.frexp.exp.f32(float %fabs.src)
+  store i32 %frexp.exp, i32 addrspace(1)* %out
+  ret void
+}
+
+; GCN-LABEL: {{^}}s_test_fneg_fabs_frexp_exp_f32:
+; GCN: v_frexp_exp_i32_f32_e64 {{v[0-9]+}}, -|{{s[0-9]+}}|
+define void @s_test_fneg_fabs_frexp_exp_f32(i32 addrspace(1)* %out, float %src) #1 {
+  %fabs.src = call float @llvm.fabs.f32(float %src)
+  %fneg.fabs.src = fsub float -0.0, %fabs.src
+  %frexp.exp = call i32 @llvm.amdgcn.frexp.exp.f32(float %fneg.fabs.src)
+  store i32 %frexp.exp, i32 addrspace(1)* %out
+  ret void
+}
+
+; GCN-LABEL: {{^}}s_test_frexp_exp_f64:
+; GCN: v_frexp_exp_i32_f64_e32 {{v[0-9]+}}, {{s\[[0-9]+:[0-9]+\]}}
+define void @s_test_frexp_exp_f64(i32 addrspace(1)* %out, double %src) #1 {
+  %frexp.exp = call i32 @llvm.amdgcn.frexp.exp.f64(double %src)
+  store i32 %frexp.exp, i32 addrspace(1)* %out
+  ret void
+}
+
+; GCN-LABEL: {{^}}s_test_fabs_frexp_exp_f64:
+; GCN: v_frexp_exp_i32_f64_e64 {{v[0-9]+}}, |{{s\[[0-9]+:[0-9]+\]}}|
+define void @s_test_fabs_frexp_exp_f64(i32 addrspace(1)* %out, double %src) #1 {
+  %fabs.src = call double @llvm.fabs.f64(double %src)
+  %frexp.exp = call i32 @llvm.amdgcn.frexp.exp.f64(double %fabs.src)
+  store i32 %frexp.exp, i32 addrspace(1)* %out
+  ret void
+}
+
+; GCN-LABEL: {{^}}s_test_fneg_fabs_frexp_exp_f64:
+; GCN: v_frexp_exp_i32_f64_e64 {{v[0-9]+}}, -|{{s\[[0-9]+:[0-9]+\]}}|
+define void @s_test_fneg_fabs_frexp_exp_f64(i32 addrspace(1)* %out, double %src) #1 {
+  %fabs.src = call double @llvm.fabs.f64(double %src)
+  %fneg.fabs.src = fsub double -0.0, %fabs.src
+  %frexp.exp = call i32 @llvm.amdgcn.frexp.exp.f64(double %fneg.fabs.src)
+  store i32 %frexp.exp, i32 addrspace(1)* %out
+  ret void
+}
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }

Modified: llvm/trunk/test/Transforms/InstCombine/amdgcn-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/amdgcn-intrinsics.ll?rev=264944&r1=264943&r2=264944&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/amdgcn-intrinsics.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/amdgcn-intrinsics.ll Wed Mar 30 17:28:52 2016
@@ -200,3 +200,165 @@ define double @test_constant_fold_frexp_
   ret double %val
 }
 
+
+; --------------------------------------------------------------------
+; llvm.amdgcn.frexp.exp
+; --------------------------------------------------------------------
+
+declare i32 @llvm.amdgcn.frexp.exp.f32(float) nounwind readnone
+declare i32 @llvm.amdgcn.frexp.exp.f64(double) nounwind readnone
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_undef(
+; CHECK-NEXT: ret i32 undef
+define i32 @test_constant_fold_frexp_exp_f32_undef() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float undef)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_undef(
+; CHECK-NEXT:  ret i32 undef
+define i32 @test_constant_fold_frexp_exp_f64_undef() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double undef)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_0(
+; CHECK-NEXT: ret i32 0
+define i32 @test_constant_fold_frexp_exp_f32_0() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_0(
+; CHECK-NEXT:  ret i32 0
+define i32 @test_constant_fold_frexp_exp_f64_0() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 0.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_n0(
+; CHECK-NEXT: ret i32 0
+define i32 @test_constant_fold_frexp_exp_f32_n0() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float -0.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_n0(
+; CHECK-NEXT:  ret i32 0
+define i32 @test_constant_fold_frexp_exp_f64_n0() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double -0.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_1024(
+; CHECK-NEXT: ret i32 11
+define i32 @test_constant_fold_frexp_exp_f32_1024() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 1024.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_1024(
+; CHECK-NEXT:  ret i32 11
+define i32 @test_constant_fold_frexp_exp_f64_1024() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 1024.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_n1024(
+; CHECK-NEXT: ret i32 11
+define i32 @test_constant_fold_frexp_exp_f32_n1024() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float -1024.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_n1024(
+; CHECK-NEXT:  ret i32 11
+define i32 @test_constant_fold_frexp_exp_f64_n1024() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double -1024.0)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_1_1024(
+; CHECK-NEXT: ret i32 -9
+define i32 @test_constant_fold_frexp_exp_f32_1_1024() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0.0009765625)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_1_1024(
+; CHECK-NEXT:  ret i32 -9
+define i32 @test_constant_fold_frexp_exp_f64_1_1024() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 0.0009765625)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_nan(
+; CHECK-NEXT: ret i32 0
+define i32 @test_constant_fold_frexp_exp_f32_nan() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0x7FF8000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_nan(
+; CHECK-NEXT:  ret i32 0
+define i32 @test_constant_fold_frexp_exp_f64_nan() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 0x7FF8000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_inf(
+; CHECK-NEXT: ret i32 0
+define i32 @test_constant_fold_frexp_exp_f32_inf() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0x7FF0000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_inf(
+; CHECK-NEXT:  ret i32 0
+define i32 @test_constant_fold_frexp_exp_f64_inf() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 0x7FF0000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_ninf(
+; CHECK-NEXT: ret i32 0
+define i32 @test_constant_fold_frexp_exp_f32_ninf() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0xFFF0000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_ninf(
+; CHECK-NEXT:  ret i32 0
+define i32 @test_constant_fold_frexp_exp_f64_ninf() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 0xFFF0000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_max_num(
+; CHECK-NEXT: ret i32 128
+define i32 @test_constant_fold_frexp_exp_f32_max_num() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0x47EFFFFFE0000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_max_num(
+; CHECK-NEXT:  ret i32 1024
+define i32 @test_constant_fold_frexp_exp_f64_max_num() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 0x7FEFFFFFFFFFFFFF)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f32_min_num(
+; CHECK-NEXT: ret i32 -148
+define i32 @test_constant_fold_frexp_exp_f32_min_num() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f32(float 0x36A0000000000000)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @test_constant_fold_frexp_exp_f64_min_num(
+; CHECK-NEXT:  ret i32 -1073
+define i32 @test_constant_fold_frexp_exp_f64_min_num() nounwind {
+  %val = call i32 @llvm.amdgcn.frexp.exp.f64(double 4.940656e-324)
+  ret i32 %val
+}
+




More information about the llvm-commits mailing list