-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[PPC] Implement BCD assist builtins #101390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-ir @llvm/pr-subscribers-clang Author: Lei Huang (lei137) ChangesImplement BCD assist builtins for XL and GCC compatibility. GCC compat:
64BIT XL compat:
Full diff: https://github.com/llvm/llvm-project/pull/101390.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def
index 88ae0ce940852..261e91b06b710 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -515,6 +515,16 @@ TARGET_BUILTIN(__builtin_altivec_vctzh, "V8UsV8Us", "", "power9-vector")
TARGET_BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "", "power9-vector")
TARGET_BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "", "power9-vector")
+// P7 BCD builtins.
+TARGET_BUILTIN(__builtin_cdtbcd, "UiUi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_cbcdtd, "UiUi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_addg6s, "UiUiUi", "", "isa-v206-instructions")
+
+// P7 XL Compat BCD builtins.
+TARGET_BUILTIN(__builtin_ppc_cdtbcd, "LLiLLi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_ppc_cbcdtd, "LLiLLi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_ppc_addg6s, "LLiLLiLLi", "", "isa-v206-instructions")
+
// P8 BCD builtins.
TARGET_BUILTIN(__builtin_ppc_bcdadd, "V16UcV16UcV16UcIi", "",
"isa-v207-instructions")
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index d8203f76a5468..b5f9adfdd515b 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -105,6 +105,9 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
}
static void defineXLCompatMacros(MacroBuilder &Builder) {
+ Builder.defineMacro("__cdtbcd", "__builtin_ppc_cdtbcd");
+ Builder.defineMacro("__cbcdtd", "__builtin_ppc_cbcdtd");
+ Builder.defineMacro("__addg6s", "__builtin_ppc_addg6s");
Builder.defineMacro("__popcntb", "__builtin_ppc_popcntb");
Builder.defineMacro("__poppar4", "__builtin_ppc_poppar4");
Builder.defineMacro("__poppar8", "__builtin_ppc_poppar8");
diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp
index 5b764ed396ebc..e0a978e6cf5b9 100644
--- a/clang/lib/Sema/SemaPPC.cpp
+++ b/clang/lib/Sema/SemaPPC.cpp
@@ -61,6 +61,9 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_bpermd:
case PPC::BI__builtin_pdepd:
case PPC::BI__builtin_pextd:
+ case PPC::BI__builtin_ppc_cdtbcd:
+ case PPC::BI__builtin_ppc_cbcdtd:
+ case PPC::BI__builtin_ppc_addg6s:
case PPC::BI__builtin_ppc_ldarx:
case PPC::BI__builtin_ppc_stdcx:
case PPC::BI__builtin_ppc_tdw:
diff --git a/clang/test/CodeGen/PowerPC/builtins-bcd-assist.c b/clang/test/CodeGen/PowerPC/builtins-bcd-assist.c
new file mode 100644
index 0000000000000..f346bcf7322c6
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/builtins-bcd-assist.c
@@ -0,0 +1,58 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i64 @cdtbcd_test(i64
+// CHECK: [[CONV:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cdtbcd(i32 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT: ret i64 [[CONV1]]
+long long cdtbcd_test(long long ll) {
+ return __builtin_cdtbcd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cdtbcd_test_ui(i32
+// CHECK: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cdtbcd(i32
+// CHECK-NEXT: ret i32 [[TMP0]]
+unsigned int cdtbcd_test_ui(unsigned int ui) {
+ return __builtin_cdtbcd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @cbcdtd_test(i64
+// CHECK: [[CONV:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cbcdtd(i32 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT: ret i64 [[CONV1]]
+long long cbcdtd_test(long long ll) {
+ return __builtin_cbcdtd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cbcdtd_test_ui(i32
+// CHECK: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cbcdtd(i32
+// CHECK-NEXT: ret i32 [[TMP0]]
+unsigned int cbcdtd_test_ui(unsigned int ui) {
+ return __builtin_cbcdtd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @addg6s_test(i64
+// CHECK: [[CONV:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.addg6s(i32 [[CONV]], i32 [[CONV1]])
+// CHECK-NEXT: [[CONV2:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT: ret i64 [[CONV2]]
+//
+long long addg6s_test(long long ll, long long ll2) {
+ return __builtin_addg6s (ll, ll2);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @addg6s_test_ui(i32
+// CHECK: [[TMP0:%.*]] = tail call i32 @llvm.ppc.addg6s(i32 {{.*}}, i32
+// CHECK-NEXT: ret i32 [[TMP0]]
+unsigned int addg6s_test_ui(unsigned int ui, unsigned int ui2) {
+ return __builtin_addg6s (ui, ui2);
+}
diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.c b/clang/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.c
new file mode 100644
index 0000000000000..79d2da2006e0a
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.c
@@ -0,0 +1,75 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: not %clang_cc1 -triple powerpc-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-32-ERROR
+
+// CHECK-LABEL: define{{.*}} i64 @cdtbcd_test(i64
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cdtbcdd(i64
+// CHECK-NEXT: ret i64 [[TMP0]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cdtbcd __builtin_ppc_cdtbcd
+long long cdtbcd_test(long long ll) {
+ return __cdtbcd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cdtbcd_test_ui(i32
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cdtbcdd(i64 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[TMP0]] to i32
+// CHECK-NEXT: ret i32 [[CONV1]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cdtbcd __builtin_ppc_cdtbcd
+unsigned int cdtbcd_test_ui(unsigned int ui) {
+ return __cdtbcd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @cbcdtd_test(i64
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cbcdtdd(i64
+// CHECK-NEXT: ret i64 [[TMP0]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cbcdtd __builtin_ppc_cbcdtd
+long long cbcdtd_test(long long ll) {
+ return __cbcdtd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cbcdtd_test_ui(i32
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cbcdtdd(i64 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[TMP0]] to i32
+// CHECK-NEXT: ret i32 [[CONV1]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cbcdtd __builtin_ppc_cbcdtd
+unsigned int cbcdtd_test_ui(unsigned int ui) {
+ return __cbcdtd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @addg6s_test(i64
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.addg6sd(i64 {{.*}}, i64 {{.*}})
+// CHECK-NEXT: ret i64 [[TMP0]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __addg6s __builtin_ppc_addg6s
+long long addg6s_test(long long ll, long long ll2) {
+ return __addg6s (ll, ll2);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @addg6s_test_ui(i32
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[CONV1:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.addg6sd(i64 {{.*}}, i64
+// CHECK-NEXT: [[CONV2:%.*]] = trunc i64 [[TMP0]] to i32
+// CHECK-NEXT: ret i32 [[CONV2]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __addg6s __builtin_ppc_addg6s
+unsigned int addg6s_test_ui(unsigned int ui, unsigned int ui2) {
+ return __addg6s (ui, ui2);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index aff1fc7f085c4..6f49ed39d8a09 100644
--- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -632,6 +632,19 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
DefaultAttrsIntrinsic<[llvm_v1i128_ty],[llvm_v1i128_ty],[IntrNoMem]>;
// BCD intrinsics.
+ def int_ppc_cdtbcdd : ClangBuiltin<"__builtin_ppc_cdtbcd">,
+ DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
+ def int_ppc_cbcdtdd: ClangBuiltin<"__builtin_ppc_cbcdtd">,
+ DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
+ def int_ppc_addg6sd: ClangBuiltin<"__builtin_ppc_addg6s">,
+ DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_ppc_cdtbcd : ClangBuiltin<"__builtin_cdtbcd">,
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
+ def int_ppc_cbcdtd: ClangBuiltin<"__builtin_cbcdtd">,
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
+ def int_ppc_addg6s: ClangBuiltin<"__builtin_addg6s">,
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+
def int_ppc_bcdadd : ClangBuiltin<"__builtin_ppc_bcdadd">,
DefaultAttrsIntrinsic<
[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty],
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 8f5afbae01de1..0177034a5ae0f 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -1014,12 +1014,14 @@ def POPCNTB8 : XForm_11<31, 122, (outs g8rc:$RA), (ins g8rc:$RST),
[(set i64:$RA, (int_ppc_popcntb i64:$RST))]>;
def CDTBCD8 : XForm_11<31, 282, (outs g8rc:$RA), (ins g8rc:$RST),
- "cdtbcd $RA, $RST", IIC_IntGeneral, []>;
+ "cdtbcd $RA, $RST", IIC_IntGeneral,
+ [(set i64:$RA, (int_ppc_cdtbcdd i64:$RST))]>;
def CBCDTD8 : XForm_11<31, 314, (outs g8rc:$RA), (ins g8rc:$RST),
- "cbcdtd $RA, $RST", IIC_IntGeneral, []>;
-
+ "cbcdtd $RA, $RST", IIC_IntGeneral,
+ [(set i64:$RA, (int_ppc_cbcdtdd i64:$RST))]>;
def ADDG6S8 : XOForm_1<31, 74, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB),
- "addg6s $RT, $RA, $RB", IIC_IntGeneral, []>;
+ "addg6s $RT, $RA, $RB", IIC_IntGeneral,
+ [(set i64:$RT, (int_ppc_addg6sd i64:$RA, i64:$RB))]>;
}
defm DIVD : XOForm_1rcr<31, 489, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB),
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 1686249c0f89d..411ea77afc0de 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1931,12 +1931,14 @@ def POPCNTB : XForm_11<31, 122, (outs gprc:$RA), (ins gprc:$RST),
[(set i32:$RA, (int_ppc_popcntb i32:$RST))]>;
def CDTBCD : XForm_11<31, 282, (outs gprc:$RA), (ins gprc:$RST),
- "cdtbcd $RA, $RST", IIC_IntGeneral, []>;
+ "cdtbcd $RA, $RST", IIC_IntGeneral,
+ [(set i32:$RA, (int_ppc_cdtbcd i32:$RST))]>;
def CBCDTD : XForm_11<31, 314, (outs gprc:$RA), (ins gprc:$RST),
- "cbcdtd $RA, $RST", IIC_IntGeneral, []>;
-
+ "cbcdtd $RA, $RST", IIC_IntGeneral,
+ [(set i32:$RA, (int_ppc_cbcdtd i32:$RST))]>;
def ADDG6S : XOForm_1<31, 74, 0, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB),
- "addg6s $RT, $RA, $RB", IIC_IntGeneral, []>;
+ "addg6s $RT, $RA, $RB", IIC_IntGeneral,
+ [(set i32:$RT, (int_ppc_addg6s i32:$RA, i32:$RB))]>;
//===----------------------------------------------------------------------===//
// PPC32 Load Instructions.
diff --git a/llvm/test/CodeGen/PowerPC/builtins-bcd-assist.ll b/llvm/test/CodeGen/PowerPC/builtins-bcd-assist.ll
new file mode 100644
index 0000000000000..cc5d6bee3c97b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/builtins-bcd-assist.ll
@@ -0,0 +1,111 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-AIX32
+
+define dso_local i64 @cdtbcd_test(i64 noundef %ll) {
+; CHECK-LABEL: cdtbcd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cdtbcd_test:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: li r3, 0
+; CHECK-AIX32-NEXT: cdtbcd r4, r4
+; CHECK-AIX32-NEXT: blr
+entry:
+ %conv = trunc i64 %ll to i32
+ %0 = tail call i32 @llvm.ppc.cdtbcd(i32 %conv)
+ %conv1 = zext i32 %0 to i64
+ ret i64 %conv1
+}
+
+define dso_local zeroext i32 @cdtbcd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cdtbcd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cdtbcd_test_ui:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: cdtbcd r3, r3
+; CHECK-AIX32-NEXT: blr
+entry:
+ %0 = tail call i32 @llvm.ppc.cdtbcd(i32 %ui)
+ ret i32 %0
+}
+
+define dso_local i64 @cbcdtd_test(i64 noundef %ll) {
+; CHECK-LABEL: cbcdtd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cbcdtd_test:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: li r3, 0
+; CHECK-AIX32-NEXT: cbcdtd r4, r4
+; CHECK-AIX32-NEXT: blr
+entry:
+ %conv = trunc i64 %ll to i32
+ %0 = tail call [email protected](i32 %conv)
+ %conv1 = zext i32 %0 to i64
+ ret i64 %conv1
+}
+
+define dso_local zeroext i32 @cbcdtd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cbcdtd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cbcdtd_test_ui:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: cbcdtd r3, r3
+; CHECK-AIX32-NEXT: blr
+entry:
+ %0 = tail call i32 @llvm.ppc.cbcdtd(i32 %ui)
+ ret i32 %0
+}
+
+define dso_local i64 @addg6s_test(i64 noundef %ll, i64 noundef %ll2) {
+; CHECK-LABEL: addg6s_test:
+; CHECK: bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: addg6s_test:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: li r3, 0
+; CHECK-AIX32-NEXT: addg6s r4, r4, r6
+; CHECK-AIX32-NEXT: blr
+entry:
+ %conv = trunc i64 %ll to i32
+ %conv1 = trunc i64 %ll2 to i32
+ %0 = tail call i32 @llvm.ppc.addg6s(i32 %conv, i32 %conv1)
+ %conv2 = zext i32 %0 to i64
+ ret i64 %conv2
+}
+
+define dso_local zeroext i32 @addg6s_test_ui(i32 noundef zeroext %ui, i32 noundef zeroext %ui2) {
+; CHECK-LABEL: addg6s_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: addg6s_test_ui:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: addg6s r3, r3, r4
+; CHECK-AIX32-NEXT: blr
+entry:
+ %0 = tail call i32 @llvm.ppc.addg6s(i32 %ui, i32 %ui2)
+ ret i32 %0
+}
+
+declare i32 @llvm.ppc.cdtbcd(i32)
+declare i32 @llvm.ppc.cbcdtd(i32)
+declare i32 @llvm.ppc.addg6s(i32, i32)
diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.ll
new file mode 100644
index 0000000000000..d188f6014f0cb
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.ll
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+
+define i64 @cdtbcd_test(i64 noundef %ll) {
+; CHECK-LABEL: cdtbcd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: blr
+entry:
+ %0 = tail call i64 @llvm.ppc.cdtbcdd(i64 %ll)
+ ret i64 %0
+}
+
+define zeroext i32 @cdtbcd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cdtbcd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+entry:
+ %conv = zext i32 %ui to i64
+ %0 = tail call i64 @llvm.ppc.cdtbcdd(i64 %conv)
+ %conv1 = trunc i64 %0 to i32
+ ret i32 %conv1
+}
+
+define i64 @cbcdtd_test(i64 noundef %ll) {
+; CHECK-LABEL: cbcdtd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: blr
+entry:
+ %0 = tail call i64 @llvm.ppc.cbcdtdd(i64 %ll)
+ ret i64 %0
+}
+
+define zeroext i32 @cbcdtd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cbcdtd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+entry:
+ %conv = zext i32 %ui to i64
+ %0 = tail call i64 @llvm.ppc.cbcdtdd(i64 %conv)
+ %conv1 = trunc i64 %0 to i32
+ ret i32 %conv1
+}
+
+define i64 @addg6s_test(i64 noundef %ll, i64 noundef %ll2) {
+; CHECK-LABEL: addg6s_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: blr
+entry:
+ %0 = tail call i64 @llvm.ppc.addg6sd(i64 %ll, i64 %ll2)
+ ret i64 %0
+}
+
+define zeroext i32 @addg6s_test_ui(i32 noundef zeroext %ui, i32 noundef zeroext %ui2) {
+; CHECK-LABEL: addg6s_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+entry:
+ %conv = zext i32 %ui to i64
+ %conv1 = zext i32 %ui2 to i64
+ %0 = tail call i64 @llvm.ppc.addg6sd(i64 %conv, i64 %conv1)
+ %conv2 = trunc i64 %0 to i32
+ ret i32 %conv2
+}
+
+declare i64 @llvm.ppc.cdtbcdd(i64)
+declare i64 @llvm.ppc.cbcdtdd(i64)
+declare i64 @llvm.ppc.addg6sd(i64, i64)
|
@llvm/pr-subscribers-backend-powerpc Author: Lei Huang (lei137) ChangesImplement BCD assist builtins for XL and GCC compatibility. GCC compat:
64BIT XL compat:
Full diff: https://github.com/llvm/llvm-project/pull/101390.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def
index 88ae0ce940852..261e91b06b710 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -515,6 +515,16 @@ TARGET_BUILTIN(__builtin_altivec_vctzh, "V8UsV8Us", "", "power9-vector")
TARGET_BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "", "power9-vector")
TARGET_BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "", "power9-vector")
+// P7 BCD builtins.
+TARGET_BUILTIN(__builtin_cdtbcd, "UiUi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_cbcdtd, "UiUi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_addg6s, "UiUiUi", "", "isa-v206-instructions")
+
+// P7 XL Compat BCD builtins.
+TARGET_BUILTIN(__builtin_ppc_cdtbcd, "LLiLLi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_ppc_cbcdtd, "LLiLLi", "", "isa-v206-instructions")
+TARGET_BUILTIN(__builtin_ppc_addg6s, "LLiLLiLLi", "", "isa-v206-instructions")
+
// P8 BCD builtins.
TARGET_BUILTIN(__builtin_ppc_bcdadd, "V16UcV16UcV16UcIi", "",
"isa-v207-instructions")
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index d8203f76a5468..b5f9adfdd515b 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -105,6 +105,9 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
}
static void defineXLCompatMacros(MacroBuilder &Builder) {
+ Builder.defineMacro("__cdtbcd", "__builtin_ppc_cdtbcd");
+ Builder.defineMacro("__cbcdtd", "__builtin_ppc_cbcdtd");
+ Builder.defineMacro("__addg6s", "__builtin_ppc_addg6s");
Builder.defineMacro("__popcntb", "__builtin_ppc_popcntb");
Builder.defineMacro("__poppar4", "__builtin_ppc_poppar4");
Builder.defineMacro("__poppar8", "__builtin_ppc_poppar8");
diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp
index 5b764ed396ebc..e0a978e6cf5b9 100644
--- a/clang/lib/Sema/SemaPPC.cpp
+++ b/clang/lib/Sema/SemaPPC.cpp
@@ -61,6 +61,9 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_bpermd:
case PPC::BI__builtin_pdepd:
case PPC::BI__builtin_pextd:
+ case PPC::BI__builtin_ppc_cdtbcd:
+ case PPC::BI__builtin_ppc_cbcdtd:
+ case PPC::BI__builtin_ppc_addg6s:
case PPC::BI__builtin_ppc_ldarx:
case PPC::BI__builtin_ppc_stdcx:
case PPC::BI__builtin_ppc_tdw:
diff --git a/clang/test/CodeGen/PowerPC/builtins-bcd-assist.c b/clang/test/CodeGen/PowerPC/builtins-bcd-assist.c
new file mode 100644
index 0000000000000..f346bcf7322c6
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/builtins-bcd-assist.c
@@ -0,0 +1,58 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define{{.*}} i64 @cdtbcd_test(i64
+// CHECK: [[CONV:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cdtbcd(i32 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT: ret i64 [[CONV1]]
+long long cdtbcd_test(long long ll) {
+ return __builtin_cdtbcd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cdtbcd_test_ui(i32
+// CHECK: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cdtbcd(i32
+// CHECK-NEXT: ret i32 [[TMP0]]
+unsigned int cdtbcd_test_ui(unsigned int ui) {
+ return __builtin_cdtbcd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @cbcdtd_test(i64
+// CHECK: [[CONV:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cbcdtd(i32 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT: ret i64 [[CONV1]]
+long long cbcdtd_test(long long ll) {
+ return __builtin_cbcdtd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cbcdtd_test_ui(i32
+// CHECK: [[TMP0:%.*]] = tail call i32 @llvm.ppc.cbcdtd(i32
+// CHECK-NEXT: ret i32 [[TMP0]]
+unsigned int cbcdtd_test_ui(unsigned int ui) {
+ return __builtin_cbcdtd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @addg6s_test(i64
+// CHECK: [[CONV:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 {{.*}} to i32
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.addg6s(i32 [[CONV]], i32 [[CONV1]])
+// CHECK-NEXT: [[CONV2:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT: ret i64 [[CONV2]]
+//
+long long addg6s_test(long long ll, long long ll2) {
+ return __builtin_addg6s (ll, ll2);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @addg6s_test_ui(i32
+// CHECK: [[TMP0:%.*]] = tail call i32 @llvm.ppc.addg6s(i32 {{.*}}, i32
+// CHECK-NEXT: ret i32 [[TMP0]]
+unsigned int addg6s_test_ui(unsigned int ui, unsigned int ui2) {
+ return __builtin_addg6s (ui, ui2);
+}
diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.c b/clang/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.c
new file mode 100644
index 0000000000000..79d2da2006e0a
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.c
@@ -0,0 +1,75 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+// RUN: not %clang_cc1 -triple powerpc-unknown-aix -O2 -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-32-ERROR
+
+// CHECK-LABEL: define{{.*}} i64 @cdtbcd_test(i64
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cdtbcdd(i64
+// CHECK-NEXT: ret i64 [[TMP0]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cdtbcd __builtin_ppc_cdtbcd
+long long cdtbcd_test(long long ll) {
+ return __cdtbcd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cdtbcd_test_ui(i32
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cdtbcdd(i64 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[TMP0]] to i32
+// CHECK-NEXT: ret i32 [[CONV1]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cdtbcd __builtin_ppc_cdtbcd
+unsigned int cdtbcd_test_ui(unsigned int ui) {
+ return __cdtbcd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @cbcdtd_test(i64
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cbcdtdd(i64
+// CHECK-NEXT: ret i64 [[TMP0]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cbcdtd __builtin_ppc_cbcdtd
+long long cbcdtd_test(long long ll) {
+ return __cbcdtd (ll);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @cbcdtd_test_ui(i32
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.cbcdtdd(i64 [[CONV]])
+// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[TMP0]] to i32
+// CHECK-NEXT: ret i32 [[CONV1]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __cbcdtd __builtin_ppc_cbcdtd
+unsigned int cbcdtd_test_ui(unsigned int ui) {
+ return __cbcdtd (ui);
+}
+
+// CHECK-LABEL: define{{.*}} i64 @addg6s_test(i64
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.addg6sd(i64 {{.*}}, i64 {{.*}})
+// CHECK-NEXT: ret i64 [[TMP0]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __addg6s __builtin_ppc_addg6s
+long long addg6s_test(long long ll, long long ll2) {
+ return __addg6s (ll, ll2);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @addg6s_test_ui(i32
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[CONV1:%.*]] = zext i32 {{.*}} to i64
+// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.addg6sd(i64 {{.*}}, i64
+// CHECK-NEXT: [[CONV2:%.*]] = trunc i64 [[TMP0]] to i32
+// CHECK-NEXT: ret i32 [[CONV2]]
+// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
+// CHECK-32-ERROR: #define __addg6s __builtin_ppc_addg6s
+unsigned int addg6s_test_ui(unsigned int ui, unsigned int ui2) {
+ return __addg6s (ui, ui2);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index aff1fc7f085c4..6f49ed39d8a09 100644
--- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -632,6 +632,19 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
DefaultAttrsIntrinsic<[llvm_v1i128_ty],[llvm_v1i128_ty],[IntrNoMem]>;
// BCD intrinsics.
+ def int_ppc_cdtbcdd : ClangBuiltin<"__builtin_ppc_cdtbcd">,
+ DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
+ def int_ppc_cbcdtdd: ClangBuiltin<"__builtin_ppc_cbcdtd">,
+ DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
+ def int_ppc_addg6sd: ClangBuiltin<"__builtin_ppc_addg6s">,
+ DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>;
+ def int_ppc_cdtbcd : ClangBuiltin<"__builtin_cdtbcd">,
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
+ def int_ppc_cbcdtd: ClangBuiltin<"__builtin_cbcdtd">,
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
+ def int_ppc_addg6s: ClangBuiltin<"__builtin_addg6s">,
+ DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
+
def int_ppc_bcdadd : ClangBuiltin<"__builtin_ppc_bcdadd">,
DefaultAttrsIntrinsic<
[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty],
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 8f5afbae01de1..0177034a5ae0f 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -1014,12 +1014,14 @@ def POPCNTB8 : XForm_11<31, 122, (outs g8rc:$RA), (ins g8rc:$RST),
[(set i64:$RA, (int_ppc_popcntb i64:$RST))]>;
def CDTBCD8 : XForm_11<31, 282, (outs g8rc:$RA), (ins g8rc:$RST),
- "cdtbcd $RA, $RST", IIC_IntGeneral, []>;
+ "cdtbcd $RA, $RST", IIC_IntGeneral,
+ [(set i64:$RA, (int_ppc_cdtbcdd i64:$RST))]>;
def CBCDTD8 : XForm_11<31, 314, (outs g8rc:$RA), (ins g8rc:$RST),
- "cbcdtd $RA, $RST", IIC_IntGeneral, []>;
-
+ "cbcdtd $RA, $RST", IIC_IntGeneral,
+ [(set i64:$RA, (int_ppc_cbcdtdd i64:$RST))]>;
def ADDG6S8 : XOForm_1<31, 74, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB),
- "addg6s $RT, $RA, $RB", IIC_IntGeneral, []>;
+ "addg6s $RT, $RA, $RB", IIC_IntGeneral,
+ [(set i64:$RT, (int_ppc_addg6sd i64:$RA, i64:$RB))]>;
}
defm DIVD : XOForm_1rcr<31, 489, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB),
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 1686249c0f89d..411ea77afc0de 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1931,12 +1931,14 @@ def POPCNTB : XForm_11<31, 122, (outs gprc:$RA), (ins gprc:$RST),
[(set i32:$RA, (int_ppc_popcntb i32:$RST))]>;
def CDTBCD : XForm_11<31, 282, (outs gprc:$RA), (ins gprc:$RST),
- "cdtbcd $RA, $RST", IIC_IntGeneral, []>;
+ "cdtbcd $RA, $RST", IIC_IntGeneral,
+ [(set i32:$RA, (int_ppc_cdtbcd i32:$RST))]>;
def CBCDTD : XForm_11<31, 314, (outs gprc:$RA), (ins gprc:$RST),
- "cbcdtd $RA, $RST", IIC_IntGeneral, []>;
-
+ "cbcdtd $RA, $RST", IIC_IntGeneral,
+ [(set i32:$RA, (int_ppc_cbcdtd i32:$RST))]>;
def ADDG6S : XOForm_1<31, 74, 0, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB),
- "addg6s $RT, $RA, $RB", IIC_IntGeneral, []>;
+ "addg6s $RT, $RA, $RB", IIC_IntGeneral,
+ [(set i32:$RT, (int_ppc_addg6s i32:$RA, i32:$RB))]>;
//===----------------------------------------------------------------------===//
// PPC32 Load Instructions.
diff --git a/llvm/test/CodeGen/PowerPC/builtins-bcd-assist.ll b/llvm/test/CodeGen/PowerPC/builtins-bcd-assist.ll
new file mode 100644
index 0000000000000..cc5d6bee3c97b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/builtins-bcd-assist.ll
@@ -0,0 +1,111 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-AIX32
+
+define dso_local i64 @cdtbcd_test(i64 noundef %ll) {
+; CHECK-LABEL: cdtbcd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cdtbcd_test:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: li r3, 0
+; CHECK-AIX32-NEXT: cdtbcd r4, r4
+; CHECK-AIX32-NEXT: blr
+entry:
+ %conv = trunc i64 %ll to i32
+ %0 = tail call i32 @llvm.ppc.cdtbcd(i32 %conv)
+ %conv1 = zext i32 %0 to i64
+ ret i64 %conv1
+}
+
+define dso_local zeroext i32 @cdtbcd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cdtbcd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cdtbcd_test_ui:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: cdtbcd r3, r3
+; CHECK-AIX32-NEXT: blr
+entry:
+ %0 = tail call i32 @llvm.ppc.cdtbcd(i32 %ui)
+ ret i32 %0
+}
+
+define dso_local i64 @cbcdtd_test(i64 noundef %ll) {
+; CHECK-LABEL: cbcdtd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cbcdtd_test:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: li r3, 0
+; CHECK-AIX32-NEXT: cbcdtd r4, r4
+; CHECK-AIX32-NEXT: blr
+entry:
+ %conv = trunc i64 %ll to i32
+ %0 = tail call [email protected](i32 %conv)
+ %conv1 = zext i32 %0 to i64
+ ret i64 %conv1
+}
+
+define dso_local zeroext i32 @cbcdtd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cbcdtd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: cbcdtd_test_ui:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: cbcdtd r3, r3
+; CHECK-AIX32-NEXT: blr
+entry:
+ %0 = tail call i32 @llvm.ppc.cbcdtd(i32 %ui)
+ ret i32 %0
+}
+
+define dso_local i64 @addg6s_test(i64 noundef %ll, i64 noundef %ll2) {
+; CHECK-LABEL: addg6s_test:
+; CHECK: bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: addg6s_test:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: li r3, 0
+; CHECK-AIX32-NEXT: addg6s r4, r4, r6
+; CHECK-AIX32-NEXT: blr
+entry:
+ %conv = trunc i64 %ll to i32
+ %conv1 = trunc i64 %ll2 to i32
+ %0 = tail call i32 @llvm.ppc.addg6s(i32 %conv, i32 %conv1)
+ %conv2 = zext i32 %0 to i64
+ ret i64 %conv2
+}
+
+define dso_local zeroext i32 @addg6s_test_ui(i32 noundef zeroext %ui, i32 noundef zeroext %ui2) {
+; CHECK-LABEL: addg6s_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+; CHECK-AIX32-LABEL: addg6s_test_ui:
+; CHECK-AIX32: # %bb.0: # %entry
+; CHECK-AIX32-NEXT: addg6s r3, r3, r4
+; CHECK-AIX32-NEXT: blr
+entry:
+ %0 = tail call i32 @llvm.ppc.addg6s(i32 %ui, i32 %ui2)
+ ret i32 %0
+}
+
+declare i32 @llvm.ppc.cdtbcd(i32)
+declare i32 @llvm.ppc.cbcdtd(i32)
+declare i32 @llvm.ppc.addg6s(i32, i32)
diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.ll
new file mode 100644
index 0000000000000..d188f6014f0cb
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-bcd-assist.ll
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN: --ppc-asm-full-reg-names -mcpu=pwr7 < %s | FileCheck %s
+
+define i64 @cdtbcd_test(i64 noundef %ll) {
+; CHECK-LABEL: cdtbcd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: blr
+entry:
+ %0 = tail call i64 @llvm.ppc.cdtbcdd(i64 %ll)
+ ret i64 %0
+}
+
+define zeroext i32 @cdtbcd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cdtbcd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cdtbcd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+entry:
+ %conv = zext i32 %ui to i64
+ %0 = tail call i64 @llvm.ppc.cdtbcdd(i64 %conv)
+ %conv1 = trunc i64 %0 to i32
+ ret i32 %conv1
+}
+
+define i64 @cbcdtd_test(i64 noundef %ll) {
+; CHECK-LABEL: cbcdtd_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: blr
+entry:
+ %0 = tail call i64 @llvm.ppc.cbcdtdd(i64 %ll)
+ ret i64 %0
+}
+
+define zeroext i32 @cbcdtd_test_ui(i32 noundef zeroext %ui) {
+; CHECK-LABEL: cbcdtd_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cbcdtd r3, r3
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+entry:
+ %conv = zext i32 %ui to i64
+ %0 = tail call i64 @llvm.ppc.cbcdtdd(i64 %conv)
+ %conv1 = trunc i64 %0 to i32
+ ret i32 %conv1
+}
+
+define i64 @addg6s_test(i64 noundef %ll, i64 noundef %ll2) {
+; CHECK-LABEL: addg6s_test:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: blr
+entry:
+ %0 = tail call i64 @llvm.ppc.addg6sd(i64 %ll, i64 %ll2)
+ ret i64 %0
+}
+
+define zeroext i32 @addg6s_test_ui(i32 noundef zeroext %ui, i32 noundef zeroext %ui2) {
+; CHECK-LABEL: addg6s_test_ui:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: addg6s r3, r3, r4
+; CHECK-NEXT: clrldi r3, r3, 32
+; CHECK-NEXT: blr
+entry:
+ %conv = zext i32 %ui to i64
+ %conv1 = zext i32 %ui2 to i64
+ %0 = tail call i64 @llvm.ppc.addg6sd(i64 %conv, i64 %conv1)
+ %conv2 = trunc i64 %0 to i32
+ ret i32 %conv2
+}
+
+declare i64 @llvm.ppc.cdtbcdd(i64)
+declare i64 @llvm.ppc.cbcdtdd(i64)
+declare i64 @llvm.ppc.addg6sd(i64, i64)
|
TARGET_BUILTIN(__builtin_cdtbcd, "UiUi", "", "isa-v206-instructions") | ||
TARGET_BUILTIN(__builtin_cbcdtd, "UiUi", "", "isa-v206-instructions") | ||
TARGET_BUILTIN(__builtin_addg6s, "UiUiUi", "", "isa-v206-instructions") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's surprising that __builtin_xxx
and __builtin_ppc_xxx
has difference in signature. Does XL have these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, XL currently have these builtins and __buitin_ppc_xxx
are implemented to be compat with XL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; please give other reviewers some time before committing. Thanks!
// CHECK-NEXT: [[CONV1:%.*]] = zext i32 [[TMP0]] to i64 | ||
// CHECK-NEXT: ret i64 [[CONV1]] | ||
long long cdtbcd_test(long long ll) { | ||
return __builtin_cdtbcd (ll); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, for compatibility with GCC, maybe this is right. But this is not good as in clang we are also providing __cdtbcd()
for 64 bit inputs. Using GCC's 32-bit version will cause sacrifice of accuracy. I am not sure, for this case, should we add at least a warning and remind the user the other one can be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are only providing __xxx()
in 64bit for backward compat to XL. Doc will be updated to ask user to use __builtin_xxx()
for 32bit when migrating to OpenXL. GCC __builtin_xxx()
only provide support for unsigned int
. Do we really want to direct user to a functiont that takes signed long long
type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really want to direct user to a functiont that takes
signed long long
type?
Some users can benefit from the XL version of the functions even if they are not migrating from XL; however, they would need to be willing to have code that is specific to 64-bit IBM XL and Clang. The 64-bit versions of __cbcdtd
and __cdtbcd
operate on two 32-bit operands at the same time. The 64-bit version of addg6s
operates on wider BCD operands.
Also, to be clear, we are only redirecting users of __cbcdtd
and __cdtbcd
in 32-bit mode to the GCC versions (where they might need to call the GCC built-in twice if they had a 64-bit input: once for the high 32-bits and once for the low 32-bits).
__addg6s
was always 64-bit only for IBM XL, so there is no migration-from-IBM-XL scenario involving 32-bit __addg6s
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really want to direct user to a function that takes signed long long type?
My comment above is for case when a user wants to call cdtbcd
for a 64-bit input for 64-bit mode(for new codes). If the GCC compat one __builtin_cdtbcd()
is chosen by accident(this is not rejected in this patch, although GCC builtin should only accept 32-bit input), the input will be trunc so the output will be not accurate(?). But if the XLC compat one __cdtbcd()
is used, I think the output is accurate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this patch doesn't reject 64-bit input for __builtin_cdtbcd
like it rejects 32-bit input for __cdtbcd
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like it rejects 32-bit input for
__cdtbcd
It does not do so though. It accepts (and converts) 32-bit arguments (in the C/C++ code) for __cdtbcd
(in 64-bit mode).
// CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[TMP0]] to i32 | ||
// CHECK-NEXT: ret i32 [[CONV1]] | ||
// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets | ||
// CHECK-32-ERROR: #define __cbcdtd __builtin_ppc_cbcdtd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For __cbcdtd
, 32-bit input is rejected. Otherwise, we may also need sign-ext before the cbcdtd
instruction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For __cbcdtd
, we reject it (no matter the input) in 32-bit mode because its semantic is to operate on two 32-bit words (stored in a 64-bit type). That is, if we were to accept it in 32-bit mode, it would involve two cbcdtd
instructions (and not just one): this may be a surprise for users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for the offline discussion @lei137
Implement BCD assist builtins for XL and GCC compatibility.
fedc7be
to
b15899e
Compare
Implement BCD assist builtins for XL and GCC compatibility.
GCC compat:
64BIT XL compat: