lei created this revision.
lei added reviewers: stefanp, nemanjai, power-llvm-team.
Herald added subscribers: shchenz, hiraditya.
lei requested review of this revision.
Herald added projects: clang, LLVM.

Implement a subset of builtins required for compatiblilty with AIX XL compiler.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D105930

Files:
  clang/include/clang/Basic/BuiltinsPPC.def
  clang/lib/Basic/Targets/PPC.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-ppc-xlcompat-error.c
  clang/test/CodeGen/builtins-ppc-xlcompat-math.c
  clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-64bit.c
  clang/test/CodeGen/builtins-ppc-xlcompat-pwr9.c
  llvm/include/llvm/IR/IntrinsicsPowerPC.td
  llvm/lib/Target/PowerPC/PPCInstrInfo.td
  llvm/lib/Target/PowerPC/PPCInstrVSX.td
  llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-math.ll
  llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-64bit.ll
  llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9.ll

Index: llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s --check-prefix=CHECK-32BIT
+
+define dso_local zeroext i32 @extract_exp(double %d) local_unnamed_addr {
+; CHECK-LABEL: extract_exp:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xsxexpdp 3, 1
+; CHECK-NEXT:    clrldi 3, 3, 32
+; CHECK-NEXT:    blr
+;
+; CHECK-32BIT-LABEL: extract_exp:
+; CHECK-32BIT:       # %bb.0: # %entry
+; CHECK-32BIT-NEXT:    xsxexpdp 3, 1
+; CHECK-32BIT-NEXT:    # kill: def $r3 killed $r3 killed $x3
+; CHECK-32BIT-NEXT:    blr
+entry:
+  %0 = tail call i32 @llvm.ppc.extract.exp(double %d)
+  ret i32 %0
+}
+declare i32 @llvm.ppc.extract.exp(double)
Index: llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-64bit.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-pwr9-64bit.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s
+
+define dso_local i64 @extract_sig(double %d) local_unnamed_addr {
+; CHECK-LABEL: extract_sig:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xsxsigdp 3, 1
+; CHECK-NEXT:    blr
+entry:
+  %0 = tail call i64 @llvm.ppc.extract.sig(double %d)
+  ret i64 %0
+}
+declare i64 @llvm.ppc.extract.sig(double)
+
+define dso_local double @insert_exp(double %d, i64 %ull) local_unnamed_addr {
+; CHECK-LABEL: insert_exp:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mffprd 3, 1
+; CHECK-NEXT:    xsiexpdp 1, 3, 4
+; CHECK-NEXT:    # kill: def $f1 killed $f1 killed $vsl1
+; CHECK-NEXT:    blr
+entry:
+  %0 = tail call double @llvm.ppc.insert.exp(double %d, i64 %ull)
+  ret double %0
+}
+declare double @llvm.ppc.insert.exp(double, i64)
Index: llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-math.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-math.ll
@@ -0,0 +1,199 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s |\
+; RUN:   FileCheck %s --check-prefix=CHECK-PWR8
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu < %s |\
+; RUN:   FileCheck %s --check-prefix=CHECK-PWR7
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix < %s |\
+; RUN:   FileCheck %s --check-prefix=CHECK-PWR7
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix -mcpu=pwr8 < %s |\
+; RUN:   FileCheck %s --check-prefix=CHECK-PWR8
+
+; Function Attrs: nounwind uwtable
+define dso_local void @mtfsb0() local_unnamed_addr #0 {
+; CHECK-PWR8-LABEL: mtfsb0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    mtfsb0 10
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: mtfsb0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    mtfsb0 10
+; CHECK-PWR7-NEXT:    blr
+entry:
+  tail call void @llvm.ppc.mtfsb0(i32 10)
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.ppc.mtfsb0(i32)
+
+; Function Attrs: nounwind uwtable
+define dso_local void @mtfsb1() local_unnamed_addr #0 {
+; CHECK-PWR8-LABEL: mtfsb1:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    mtfsb1 0
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: mtfsb1:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    mtfsb1 0
+; CHECK-PWR7-NEXT:    blr
+entry:
+  tail call void @llvm.ppc.mtfsb1(i32 0)
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.ppc.mtfsb1(i32)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local double @fmsub_t0(double %d, double %d2, double %d3) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fmsub_t0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsmsubmdp 1, 2, 3
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fmsub_t0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fmsub 1, 1, 2, 3
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call double @llvm.ppc.fmsub(double %d, double %d2, double %d3)
+  ret double %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare double @llvm.ppc.fmsub(double, double, double)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local float @fmsubs_t0(float %f, float %f2, float %f3) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fmsubs_t0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsmsubmsp 1, 2, 3
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fmsubs_t0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fmsubs 1, 1, 2, 3
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call float @llvm.ppc.fmsubs(float %f, float %f2, float %f3)
+  ret float %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare float @llvm.ppc.fmsubs(float, float, float)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local double @fnmadd_t0(double %d, double %d2, double %d3) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fnmadd_t0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsnmaddmdp 1, 2, 3
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fnmadd_t0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fnmadd 1, 1, 2, 3
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call double @llvm.ppc.fnmadd(double %d, double %d2, double %d3)
+  ret double %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare double @llvm.ppc.fnmadd(double, double, double)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local float @fnmadds_t0(float %f, float %f2, float %f3) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fnmadds_t0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsnmaddmsp 1, 2, 3
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fnmadds_t0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fnmadds 1, 1, 2, 3
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call float @llvm.ppc.fnmadds(float %f, float %f2, float %f3)
+  ret float %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare float @llvm.ppc.fnmadds(float, float, float)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local double @fnmsub_t0(double %d, double %d2, double %d3) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fnmsub_t0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsnmsubmdp 1, 2, 3
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fnmsub_t0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fnmsub 1, 1, 2, 3
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call double @llvm.ppc.fnmsub(double %d, double %d2, double %d3)
+  ret double %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare double @llvm.ppc.fnmsub(double, double, double)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local float @fnmsubs_t0(float %f, float %f2, float %f3) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fnmsubs_t0:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsnmsubmsp 1, 2, 3
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fnmsubs_t0:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fnmsubs 1, 1, 2, 3
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call float @llvm.ppc.fnmsubs(float %f, float %f2, float %f3)
+  ret float %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare float @llvm.ppc.fnmsubs(float, float, float)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local double @fre(double %d) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fre:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsredp 1, 1
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fre:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fre 1, 1
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call double @llvm.ppc.fre(double %d)
+  ret double %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare double @llvm.ppc.fre(double)
+
+; Function Attrs: mustprogress nofree nosync nounwind readnone uwtable willreturn
+define dso_local float @fres(float %f) local_unnamed_addr {
+; CHECK-PWR8-LABEL: fres:
+; CHECK-PWR8:       # %bb.0: # %entry
+; CHECK-PWR8-NEXT:    xsresp 1, 1
+; CHECK-PWR8-NEXT:    blr
+;
+; CHECK-PWR7-LABEL: fres:
+; CHECK-PWR7:       # %bb.0: # %entry
+; CHECK-PWR7-NEXT:    fres 1, 1
+; CHECK-PWR7-NEXT:    blr
+entry:
+  %0 = tail call float @llvm.ppc.fres(float %f)
+  ret float %0
+}
+
+; Function Attrs: nofree nosync nounwind readnone
+declare float @llvm.ppc.fres(float)
Index: llvm/lib/Target/PowerPC/PPCInstrVSX.td
===================================================================
--- llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -1539,10 +1539,10 @@
 
   // Insert Exponent DP/QP
   // XT NOTE: XT.dword[1] = 0xUUUU_UUUU_UUUU_UUUU
+  def XSIEXPDP : XX1Form <60, 918, (outs vsrc:$XT), (ins g8rc:$rA, g8rc:$rB),
+                          "xsiexpdp $XT, $rA, $rB", IIC_VecFP, []>;
   // FIXME: Setting the hasSideEffects flag here to match current behaviour.
   let hasSideEffects = 1 in {
-    def XSIEXPDP : XX1Form <60, 918, (outs vsrc:$XT), (ins g8rc:$rA, g8rc:$rB),
-                            "xsiexpdp $XT, $rA, $rB", IIC_VecFP, []>;
     // vB NOTE: only vB.dword[0] is used, that's why we don't use
     //          X_VT5_VA5_VB5 form
     def XSIEXPQP : XForm_18<63, 868, (outs vrrc:$vT), (ins vrrc:$vA, vsfrc:$vB),
@@ -1550,11 +1550,11 @@
   }
 
   // Extract Exponent/Significand DP/QP
+  def XSXEXPDP : XX2_RT5_XO5_XB6<60,  0, 347, "xsxexpdp", []>;
+  def XSXSIGDP : XX2_RT5_XO5_XB6<60,  1, 347, "xsxsigdp", []>;
+
   // FIXME: Setting the hasSideEffects flag here to match current behaviour.
   let hasSideEffects = 1 in {
-    def XSXEXPDP : XX2_RT5_XO5_XB6<60,  0, 347, "xsxexpdp", []>;
-    def XSXSIGDP : XX2_RT5_XO5_XB6<60,  1, 347, "xsxsigdp", []>;
-
     def XSXEXPQP : X_VT5_XO5_VB5  <63,  2, 804, "xsxexpqp", []>;
     def XSXSIGQP : X_VT5_XO5_VB5  <63, 18, 804, "xsxsigqp", []>;
   }
@@ -2850,6 +2850,12 @@
 def : Pat<(v2i64 (PPCvcmp_rec v2i64:$vA, v2i64:$vB, 199)),
           (VCMPGTUB_rec DblwdCmp.MRGEQ, (v2i64 (XXLXORz)))>;
 } // AddedComplexity = 0
+
+// XL Compat builtins.
+def : Pat<(int_ppc_fmsub f64:$A, f64:$B, f64:$C), (XSMSUBMDP $A, $B, $C)>;
+def : Pat<(int_ppc_fnmsub f64:$A, f64:$B, f64:$C), (XSNMSUBMDP $A, $B, $C)>;
+def : Pat<(int_ppc_fnmadd f64:$A, f64:$B, f64:$C), (XSNMADDMDP $A, $B, $C)>;
+def : Pat<(int_ppc_fre f64:$A), (XSREDP $A)>;
 } // HasVSX
 
 // Any big endian VSX subtarget.
@@ -3240,6 +3246,18 @@
           (v8i16 (COPY_TO_REGCLASS(XXLEQVOnes), VSRC))>;
 def : Pat<(v16i8 (bitconvert (v16i8 immAllOnesV))),
           (v16i8 (COPY_TO_REGCLASS(XXLEQVOnes), VSRC))>;
+
+// XL Compat builtins.
+def : Pat<(int_ppc_fmsubs f32:$A, f32:$B, f32:$C), (XSMSUBMSP $A, $B, $C)>;
+def : Pat<(int_ppc_fnmsubs f32:$A, f32:$B, f32:$C), (XSNMSUBMSP $A, $B, $C)>;
+def : Pat<(int_ppc_fnmadds f32:$A, f32:$B, f32:$C), (XSNMADDMSP $A, $B, $C)>;
+def : Pat<(int_ppc_fres f32:$A), (XSRESP $A)>;
+def : Pat<(i32 (int_ppc_extract_exp f64:$A)),
+          (EXTRACT_SUBREG (XSXEXPDP (COPY_TO_REGCLASS $A, VSFRC)), sub_32)>;
+def : Pat<(int_ppc_extract_sig f64:$A),
+          (XSXSIGDP (COPY_TO_REGCLASS $A, VSFRC))>;
+def : Pat<(f64 (int_ppc_insert_exp f64:$A, i64:$B)),
+          (COPY_TO_REGCLASS (XSIEXPDP (COPY_TO_REGCLASS $A, G8RC), $B), F8RC)>;
 } // HasVSX, HasP8Vector
 
 // Any big endian Power8 VSX subtarget.
Index: llvm/lib/Target/PowerPC/PPCInstrInfo.td
===================================================================
--- llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -3084,12 +3084,16 @@
 
 // When FM is 30/31, we are setting the 62/63 bit of FPSCR, the implicit-def
 // RM should be set.
+let hasSideEffects = 1 in {
 def MTFSB0 : XForm_43<63, 70, (outs), (ins u5imm:$FM),
-                      "mtfsb0 $FM", IIC_IntMTFSB0, []>,
+                      "mtfsb0 $FM", IIC_IntMTFSB0,
+                      [(int_ppc_mtfsb0 imm:$FM)]>,
              PPC970_DGroup_Single, PPC970_Unit_FPU;
 def MTFSB1 : XForm_43<63, 38, (outs), (ins u5imm:$FM),
-                      "mtfsb1 $FM", IIC_IntMTFSB0, []>,
+                      "mtfsb1 $FM", IIC_IntMTFSB0,
+                      [(int_ppc_mtfsb1 imm:$FM)]>,
              PPC970_DGroup_Single, PPC970_Unit_FPU;
+}
 
 let Defs = [RM] in {
   let isCodeGenOnly = 1 in
@@ -3642,6 +3646,16 @@
           (FCPSGNS (COPY_TO_REGCLASS $frA, F4RC), $frB)>;
 }
 
+// XL Compat intrinsics.
+def : Pat<(int_ppc_fmsub f64:$A, f64:$B, f64:$C), (FMSUB $A, $B, $C)>;
+def : Pat<(int_ppc_fmsubs f32:$A, f32:$B, f32:$C), (FMSUBS $A, $B, $C)>;
+def : Pat<(int_ppc_fnmsub f64:$A, f64:$B, f64:$C), (FNMSUB $A, $B, $C)>;
+def : Pat<(int_ppc_fnmsubs f32:$A, f32:$B, f32:$C), (FNMSUBS $A, $B, $C)>;
+def : Pat<(int_ppc_fnmadd f64:$A, f64:$B, f64:$C), (FNMADD $A, $B, $C)>;
+def : Pat<(int_ppc_fnmadds f32:$A, f32:$B, f32:$C), (FNMADDS $A, $B, $C)>;
+def : Pat<(int_ppc_fre f64:$A), (FRE $A)>;
+def : Pat<(int_ppc_fres f32:$A), (FRES $A)>;
+
 include "PPCInstrAltivec.td"
 include "PPCInstrSPE.td"
 include "PPCInstr64Bit.td"
Index: llvm/include/llvm/IR/IntrinsicsPowerPC.td
===================================================================
--- llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -1565,5 +1565,66 @@
   def int_ppc_stwcx : GCCBuiltin<"__builtin_ppc_stwcx">,
                       Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
                                 [IntrWriteMem]>;
+  def int_ppc_insert_exp
+      : GCCBuiltin<"__builtin_ppc_insert_exp">,
+        Intrinsic <[llvm_double_ty], [llvm_double_ty, llvm_i64_ty],
+                   [IntrNoMem]>;
+  def int_ppc_extract_exp
+      : GCCBuiltin<"__builtin_ppc_extract_exp">,
+        Intrinsic <[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>;
+  def int_ppc_extract_sig
+      : GCCBuiltin<"__builtin_ppc_extract_sig">,
+        Intrinsic <[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>;
+  def int_ppc_mtfsb0
+      : GCCBuiltin<"__builtin_ppc_mtfsb0">,
+        Intrinsic <[], [llvm_i32_ty],
+                   [IntrNoMem, IntrHasSideEffects]>;
+  def int_ppc_mtfsb1
+      : GCCBuiltin<"__builtin_ppc_mtfsb1">,
+        Intrinsic <[], [llvm_i32_ty],
+                   [IntrNoMem, IntrHasSideEffects]>;
+  def int_ppc_mtfsf
+      : GCCBuiltin<"__builtin_ppc_mtfsf">,
+        Intrinsic <[], [llvm_i32_ty, llvm_i32_ty],
+                   [IntrNoMem, IntrHasSideEffects]>;
+  def int_ppc_mtfsfi
+      : GCCBuiltin<"__builtin_ppc_mtfsfi">,
+        Intrinsic <[], [llvm_i32_ty, llvm_i32_ty],
+                   [IntrNoMem, IntrHasSideEffects]>;
+  def int_ppc_fmsub
+      : GCCBuiltin<"__builtin_ppc_fmsub">,
+        Intrinsic <[llvm_double_ty],
+                   [llvm_double_ty, llvm_double_ty, llvm_double_ty],
+                   [IntrNoMem]>;
+  def int_ppc_fmsubs
+      : GCCBuiltin<"__builtin_ppc_fmsubs">,
+        Intrinsic <[llvm_float_ty],
+                   [llvm_float_ty, llvm_float_ty, llvm_float_ty],
+                   [IntrNoMem]>;
+  def int_ppc_fnmadd
+      : GCCBuiltin<"__builtin_ppc_fnmadd">,
+        Intrinsic <[llvm_double_ty],
+                   [llvm_double_ty, llvm_double_ty, llvm_double_ty],
+                   [IntrNoMem]>;
+  def int_ppc_fnmadds
+      : GCCBuiltin<"__builtin_ppc_fnmadds">,
+        Intrinsic <[llvm_float_ty],
+                   [llvm_float_ty, llvm_float_ty, llvm_float_ty],
+                   [IntrNoMem]>;
+  def int_ppc_fnmsub
+      : GCCBuiltin<"__builtin_ppc_fnmsub">,
+        Intrinsic <[llvm_double_ty],
+                   [llvm_double_ty, llvm_double_ty, llvm_double_ty],
+                   [IntrNoMem]>;
+  def int_ppc_fnmsubs
+      : GCCBuiltin<"__builtin_ppc_fnmsubs">,
+        Intrinsic <[llvm_float_ty],
+                   [llvm_float_ty, llvm_float_ty, llvm_float_ty],
+                   [IntrNoMem]>;
+  def int_ppc_fre
+      : GCCBuiltin<"__builtin_ppc_fre">,
+        Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
+  def int_ppc_fres
+      : GCCBuiltin<"__builtin_ppc_fres">,
+        Intrinsic <[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>;
 }
-
Index: clang/test/CodeGen/builtins-ppc-xlcompat-pwr9.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/builtins-ppc-xlcompat-pwr9.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix %s -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: not %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \
+// RUN:   -target-cpu pwr8 2>&1 | FileCheck %s --check-prefix=CHECK-NONPWR9-ERR
+
+unsigned int extract_exp (double d) {
+// CHECK-LABEL: @extract_exp
+// CHECK:    [[TMP1:%.*]] = call i32 @llvm.ppc.extract.exp(double %0)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+// CHECK-NONPWR9-ERR:  error: this builtin is only valid on POWER9 or later CPUs
+  return __extract_exp (d);
+}
Index: clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-64bit.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-64bit.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \
+// RUN:   -target-cpu pwr9 -o - | FileCheck %s
+// RUN: not %clang_cc1 -triple powerpc-unknown-aix %s \
+// RUN:   -target-cpu pwr9 2>&1 | FileCheck %s --check-prefix=CHECK-32-ERROR
+// RUN: not %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \
+// RUN:   -target-cpu pwr8 2>&1 | FileCheck %s --check-prefix=CHECK-NONPWR9-ERR
+
+unsigned long long extract_sig (double d) {
+// CHECK-LABEL: @extract_sig(
+// CHECK:       [[TMP1:%.*]] = call i64 @llvm.ppc.extract.sig(double %0)
+// CHECK-NEXT:  ret i64 [[TMP1]]
+//
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-NONPWR9-ERR:  error: this builtin is only valid on POWER9 or later CPUs
+  return __extract_sig (d);
+}
+
+double insert_exp (double d, unsigned long long ull) {
+// CHECK-LABEL: @insert_exp(
+// CHECK:       [[TMP2:%.*]] = call double @llvm.ppc.insert.exp(double %0, i64 %1)
+// CHECK-NEXT:    ret double [[TMP2]]
+//
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-NONPWR9-ERR:  error: this builtin is only valid on POWER9 or later CPUs
+  return __insert_exp (d, ull);
+}
Index: clang/test/CodeGen/builtins-ppc-xlcompat-math.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/builtins-ppc-xlcompat-math.c
@@ -0,0 +1,143 @@
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \
+// RUN:   -target-cpu pwr7 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \
+// RUN:   -target-cpu pwr8 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \
+// RUN:   -target-cpu pwr7 -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s \
+// RUN:   -target-cpu pwr7 -o - | FileCheck %s
+
+// CHECK-LABEL: @mtfsb0(
+// CHECK:         call void @llvm.ppc.mtfsb0(i32 10)
+// CHECK-NEXT:    ret void
+//
+void mtfsb0 () {
+  __mtfsb0 (10);
+}
+
+// CHECK-LABEL: @mtfsb1(
+// CHECK:         call void @llvm.ppc.mtfsb1(i32 0)
+// CHECK-NEXT:    ret void
+//
+void mtfsb1 () {
+  __mtfsb1 (0);
+}
+
+// CHECK-LABEL: @mtfsf(
+// CHECK:         [[UI_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[UI:%.*]], i32* [[UI_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[UI_ADDR]], align 4
+// CHECK-NEXT:    call void @llvm.ppc.mtfsf(i32 8, i32 [[TMP0]])
+// CHECK-NEXT:    ret void
+//
+void mtfsf (unsigned int ui) {
+  __mtfsf (8, ui);
+}
+
+// CHECK-LABEL: @mtfsfi(
+// CHECK:         call void @llvm.ppc.mtfsfi(i32 7, i32 15)
+// CHECK-NEXT:    ret void
+//
+void mtfsfi () {
+  __mtfsfi (7, 15);
+}
+
+// CHECK-LABEL: @fmsub(
+// CHECK:         [[D_ADDR:%.*]] = alloca double, align 8
+// CHECK-NEXT:    store double [[D:%.*]], double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.ppc.fmsub(double [[TMP0]], double [[TMP1]], double [[TMP2]])
+// CHECK-NEXT:    ret double [[TMP3]]
+//
+double fmsub (double d) {
+  return __fmsub (d, d, d);
+}
+
+// CHECK-LABEL: @fmsubs(
+// CHECK:         [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store float [[F:%.*]], float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call float @llvm.ppc.fmsubs(float [[TMP0]], float [[TMP1]], float [[TMP2]])
+// CHECK-NEXT:    ret float [[TMP3]]
+//
+float fmsubs (float f) {
+  return __fmsubs (f, f, f);
+}
+
+// CHECK-LABEL: @fnmadd(
+// CHECK:         [[D_ADDR:%.*]] = alloca double, align 8
+// CHECK-NEXT:    store double [[D:%.*]], double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.ppc.fnmadd(double [[TMP0]], double [[TMP1]], double [[TMP2]])
+// CHECK-NEXT:    ret double [[TMP3]]
+//
+double fnmadd (double d) {
+  return __fnmadd (d, d, d);
+}
+
+// CHECK-LABEL: @fnmadds(
+// CHECK:         [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store float [[F:%.*]], float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call float @llvm.ppc.fnmadds(float [[TMP0]], float [[TMP1]], float [[TMP2]])
+// CHECK-NEXT:    ret float [[TMP3]]
+//
+float fnmadds (float f) {
+  return __fnmadds (f, f, f);
+}
+
+// CHECK-LABEL: @fnmsub(
+// CHECK:         [[D_ADDR:%.*]] = alloca double, align 8
+// CHECK-NEXT:    store double [[D:%.*]], double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = call double @llvm.ppc.fnmsub(double [[TMP0]], double [[TMP1]], double [[TMP2]])
+// CHECK-NEXT:    ret double [[TMP3]]
+//
+double fnmsub (double d) {
+  return __fnmsub (d, d, d);
+}
+
+// CHECK-LABEL: @fnmsubs(
+// CHECK:         [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store float [[F:%.*]], float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = call float @llvm.ppc.fnmsubs(float [[TMP0]], float [[TMP1]], float [[TMP2]])
+// CHECK-NEXT:    ret float [[TMP3]]
+//
+float fnmsubs (float f) {
+  return __fnmsubs (f, f, f);
+}
+
+// CHECK-LABEL: @fre(
+// CHECK:         [[D_ADDR:%.*]] = alloca double, align 8
+// CHECK-NEXT:    store double [[D:%.*]], double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.ppc.fre(double [[TMP0]])
+// CHECK-NEXT:    ret double [[TMP1]]
+//
+double fre (double d) {
+  return __fre (d);
+}
+
+// CHECK-LABEL: @fres(
+// CHECK:         [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store float [[F:%.*]], float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.ppc.fres(float [[TMP0]])
+// CHECK-NEXT:    ret float [[TMP1]]
+//
+float fres (float f) {
+  return __fres (f);
+}
Index: clang/test/CodeGen/builtins-ppc-xlcompat-error.c
===================================================================
--- clang/test/CodeGen/builtins-ppc-xlcompat-error.c
+++ clang/test/CodeGen/builtins-ppc-xlcompat-error.c
@@ -17,3 +17,20 @@
 #endif
   __tw(ia, ib, 50); //expected-error {{argument value 50 is outside the valid range [0, 31]}}
 }
+
+extern unsigned int usi;
+extern double d;
+extern float f;
+
+void testMathBuiltin(void) {
+  __mtfsb0(usi); //expected-error {{argument to '__builtin_ppc_mtfsb0' must be a constant integer}}
+  __mtfsb0(32); //expected-error {{argument value 32 is outside the valid range [0, 31]}}
+  __mtfsb1(usi); //expected-error {{argument to '__builtin_ppc_mtfsb1' must be a constant integer}}
+  __mtfsb1(45); //expected-error {{argument value 45 is outside the valid range [0, 31]}}
+  __mtfsf(usi, usi); //expected-error {{argument to '__builtin_ppc_mtfsf' must be a constant integer}}
+  __mtfsf(350, usi); //expected-error {{argument value 350 is outside the valid range [0, 255]}}
+  __mtfsfi(usi, 0); //expected-error {{argument to '__builtin_ppc_mtfsfi' must be a constant integer}}
+  __mtfsfi(0, usi); //expected-error {{argument to '__builtin_ppc_mtfsfi' must be a constant integer}}
+  __mtfsfi(8, 0); //expected-error {{argument value 8 is outside the valid range [0, 7]}}
+  __mtfsfi(5, 24); //expected-error {{argument value 24 is outside the valid range [0, 15]}}
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -3269,6 +3269,8 @@
   case PPC::BI__builtin_ppc_stdcx:
   case PPC::BI__builtin_ppc_tdw:
   case PPC::BI__builtin_ppc_trapd:
+  case PPC::BI__builtin_ppc_insert_exp:
+  case PPC::BI__builtin_ppc_extract_sig:
     return true;
   }
   return false;
@@ -3360,6 +3362,19 @@
   case PPC::BI__builtin_ppc_tw:
   case PPC::BI__builtin_ppc_tdw:
     return SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
+  case PPC::BI__builtin_ppc_extract_exp:
+  case PPC::BI__builtin_ppc_extract_sig:
+  case PPC::BI__builtin_ppc_insert_exp:
+    return SemaFeatureCheck(*this, TheCall, "power9-vector",
+                            diag::err_ppc_builtin_only_on_arch, "9");
+  case PPC::BI__builtin_ppc_mtfsb0:
+  case PPC::BI__builtin_ppc_mtfsb1:
+    return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
+  case PPC::BI__builtin_ppc_mtfsf:
+    return SemaBuiltinConstantArgRange(TheCall, 0, 0, 255);
+  case PPC::BI__builtin_ppc_mtfsfi:
+    return SemaBuiltinConstantArgRange(TheCall, 0, 0, 7) ||
+           SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
 #define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
   case PPC::BI__builtin_##Name: \
     return SemaBuiltinPPCMMACall(TheCall, Types);
Index: clang/lib/Basic/Targets/PPC.cpp
===================================================================
--- clang/lib/Basic/Targets/PPC.cpp
+++ clang/lib/Basic/Targets/PPC.cpp
@@ -130,6 +130,21 @@
   Builder.defineMacro("__fctiwz", "__builtin_ppc_fctiwz");
   Builder.defineMacro("__fctudz", "__builtin_ppc_fctudz");
   Builder.defineMacro("__fctuwz", "__builtin_ppc_fctuwz");
+  Builder.defineMacro("__extract_exp", "__builtin_ppc_extract_exp");
+  Builder.defineMacro("__extract_sig", "__builtin_ppc_extract_sig");
+  Builder.defineMacro("__mtfsb0", "__builtin_ppc_mtfsb0");
+  Builder.defineMacro("__mtfsb1", "__builtin_ppc_mtfsb1");
+  Builder.defineMacro("__mtfsf", "__builtin_ppc_mtfsf");
+  Builder.defineMacro("__mtfsfi", "__builtin_ppc_mtfsfi");
+  Builder.defineMacro("__insert_exp", "__builtin_ppc_insert_exp");
+  Builder.defineMacro("__fmsub", "__builtin_ppc_fmsub");
+  Builder.defineMacro("__fmsubs", "__builtin_ppc_fmsubs");
+  Builder.defineMacro("__fnmadd", "__builtin_ppc_fnmadd");
+  Builder.defineMacro("__fnmadds", "__builtin_ppc_fnmadds");
+  Builder.defineMacro("__fnmsub", "__builtin_ppc_fnmsub");
+  Builder.defineMacro("__fnmsubs", "__builtin_ppc_fnmsubs");
+  Builder.defineMacro("__fre", "__builtin_ppc_fre");
+  Builder.defineMacro("__fres", "__builtin_ppc_fres");
 }
 
 /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
Index: clang/include/clang/Basic/BuiltinsPPC.def
===================================================================
--- clang/include/clang/Basic/BuiltinsPPC.def
+++ clang/include/clang/Basic/BuiltinsPPC.def
@@ -29,7 +29,7 @@
 #define UNALIASED_CUSTOM_BUILTIN(ID, TYPES, ACCUMULATE) \
    CUSTOM_BUILTIN(ID, ID, TYPES, ACCUMULATE)
 
-// builtins for compatibility with the XL compiler
+// XL Compatibility built-ins
 BUILTIN(__builtin_ppc_popcntb, "ULiULi", "")
 BUILTIN(__builtin_ppc_eieio, "v", "")
 BUILTIN(__builtin_ppc_iospace_eieio, "v", "")
@@ -71,6 +71,21 @@
 BUILTIN(__builtin_ppc_fctiwz, "dd", "")
 BUILTIN(__builtin_ppc_fctudz, "dd", "")
 BUILTIN(__builtin_ppc_fctuwz, "dd", "")
+BUILTIN(__builtin_ppc_extract_exp, "Uid", "")
+BUILTIN(__builtin_ppc_extract_sig, "ULLid", "")
+BUILTIN(__builtin_ppc_mtfsb0, "vUi", "")
+BUILTIN(__builtin_ppc_mtfsb1, "vUi", "")
+BUILTIN(__builtin_ppc_mtfsf, "vUiUi", "")
+BUILTIN(__builtin_ppc_mtfsfi, "vUiUi", "")
+BUILTIN(__builtin_ppc_insert_exp, "ddULLi", "")
+BUILTIN(__builtin_ppc_fmsub, "dddd", "")
+BUILTIN(__builtin_ppc_fmsubs, "ffff", "")
+BUILTIN(__builtin_ppc_fnmadd, "dddd", "")
+BUILTIN(__builtin_ppc_fnmadds, "ffff", "")
+BUILTIN(__builtin_ppc_fnmsub, "dddd", "")
+BUILTIN(__builtin_ppc_fnmsubs, "ffff", "")
+BUILTIN(__builtin_ppc_fre, "dd", "")
+BUILTIN(__builtin_ppc_fres, "ff", "")
 
 BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to