Hi echristo, wschmidt, hfinkel, kbarton,
This patch provides some of the missing instructions from ISA 2.06. Namely the
integer divide extended instructions (and associated builtins) are provided.
The record-form variants are provided but can be accessed through inline
assembly only.
Since these instructions are introduced with ISA 2.06, it is important that
they not be emitted for targets that implement an older ISA. Also, since they
are exposed in the front end through builtinins, it is important that the front
end knows not to emit the intrinsics to the back end if the target does not
support them. Therefore, this patch provides the ability to test whether the
target is Power 7 and up (and Power 8 and up) and use of the builtins is
diagnosed on older CPUs.
This diverges from GCC behaviour of controlling the builtins and instructions
with -mpopcntd since that option has very little to do with these
instructions/builtins.
Note: in a general case, a newer ISA is a superset of the previous ISA.
However, instructions are sometimes removed from the ISA. This raises the
question whether emitting instructions/builtins based on "IsPwr7Up", et. al. is
the right approach. In my opinion, it is unlikely that something that is added
in say ISA 2.06 will be removed any time soon, but I welcome other opinions.
REPOSITORY
rL LLVM
http://reviews.llvm.org/D8398
Files:
include/clang/Basic/BuiltinsPPC.def
lib/Basic/Targets.cpp
lib/CodeGen/CGBuiltin.cpp
test/CodeGen/builtins-ppc-p7-disabled.c
test/CodeGen/builtins-ppc-p7.c
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Basic/BuiltinsPPC.def
===================================================================
--- include/clang/Basic/BuiltinsPPC.def
+++ include/clang/Basic/BuiltinsPPC.def
@@ -237,6 +237,13 @@
BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "")
+// Scalar built-ins
+BUILTIN(__builtin_divwe, "SiSiSi", "")
+BUILTIN(__builtin_divweu, "UiUiUi", "")
+BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "")
+BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "")
+BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "")
+
// FIXME: Obviously incomplete.
#undef BUILTIN
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -720,6 +720,9 @@
bool HasVSX;
bool HasP8Vector;
bool HasP8Crypto;
+ bool IsPwr7Up;
+ bool IsPwr8Up;
+ bool Is64Bit;
protected:
std::string ABI;
@@ -993,6 +996,12 @@
continue;
}
+ // We do not want to emit builtins that cannot be supported by the CPU
+ IsPwr8Up = CPU == "pwr8" || CPU == "ppc64le" ||
+ getTriple().getArch() == llvm::Triple::ppc64le;
+ IsPwr7Up = CPU == "pwr7" || IsPwr8Up;
+ Is64Bit = PointerWidth == 64;
+
// TODO: Finish this list and add an assert that we've handled them
// all.
}
@@ -1201,6 +1210,11 @@
.Case("vsx", HasVSX)
.Case("power8-vector", HasP8Vector)
.Case("crypto", HasP8Crypto)
+ .Case("IsPwr7Up", IsPwr7Up)
+ .Case("IsISA206Up", IsPwr7Up)
+ .Case("IsPwr8Up", IsPwr8Up)
+ .Case("IsISA207Up", IsPwr8Up)
+ .Case("Is64Bit", Is64Bit)
.Default(false);
}
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -6378,6 +6378,46 @@
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
}
+ case PPC::BI__builtin_divwe:
+ case PPC::BI__builtin_divweu:
+ case PPC::BI__builtin_divde:
+ case PPC::BI__builtin_divdeu:
+ case PPC::BI__builtin_bpermd:
+ {
+ bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde ||
+ BuiltinID == PPC::BI__builtin_divdeu ||
+ BuiltinID == PPC::BI__builtin_bpermd;
+ if(!getTarget().hasFeature("IsPwr7Up")) {
+ CGM.Error(E->getExprLoc(),
+ "This builtin is only valid on POWER7 or later CPUs");
+ return llvm::UndefValue::get(Ops[0]->getType());
+ }
+ if(!getTarget().hasFeature("Is64Bit") && Is64BitBltin) {
+ CGM.Error(E->getExprLoc(),
+ "This builtin is only available on 64-bit targets");
+ return llvm::UndefValue::get(Ops[0]->getType());
+ }
+ switch(BuiltinID) {
+ default: llvm_unreachable("Unsupported division intrinsic");
+ case PPC::BI__builtin_divwe:
+ ID = Intrinsic::ppc_divwe;
+ break;
+ case PPC::BI__builtin_divweu:
+ ID = Intrinsic::ppc_divweu;
+ break;
+ case PPC::BI__builtin_divde:
+ ID = Intrinsic::ppc_divde;
+ break;
+ case PPC::BI__builtin_divdeu:
+ ID = Intrinsic::ppc_divdeu;
+ break;
+ case PPC::BI__builtin_bpermd:
+ ID = Intrinsic::ppc_bpermd;
+ break;
+ }
+ llvm::Function *F = CGM.getIntrinsic(ID);
+ return Builder.CreateCall(F, Ops, "");
+ }
}
}
Index: test/CodeGen/builtins-ppc-p7-disabled.c
===================================================================
--- test/CodeGen/builtins-ppc-p7-disabled.c
+++ test/CodeGen/builtins-ppc-p7-disabled.c
@@ -0,0 +1,33 @@
+// REQUIRES: powerpc-registered-target
+// RUN: not %clang_cc1 -triple powerpc64-unknown-unknown \
+// RUN: -target-cpu pwr6 -emit-llvm %s -o - 2>&1 \
+// RUN: | FileCheck %s
+
+// RUN: not %clang_cc1 -triple powerpc-unknown-unknown -emit-llvm %s -o - 2>&1 \
+// RUN: -target-cpu pwr7 | FileCheck %s -check-prefix=CHECK-32
+
+void call_p7_builtins(void)
+{
+ int a = __builtin_divwe(33, 11);
+ unsigned int b = __builtin_divweu(33U, 11U);
+ unsigned long long d = __builtin_divde(33ULL, 11ULL);
+ unsigned long long e = __builtin_divdeu(33ULL, 11ULL);
+ unsigned long long f = __builtin_bpermd(33ULL, 11ULL);
+}
+
+// CHECK: error: This builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_divwe
+// CHECK: error: This builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_divweu
+// CHECK: error: This builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_divde
+// CHECK: error: This builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_divdeu
+// CHECK: error: This builtin is only valid on POWER7 or later CPUs
+// CHECK: __builtin_bpermd
+// CHECK-32: error: This builtin is only available on 64-bit targets
+// CHECK-32: __builtin_divde
+// CHECK-32: error: This builtin is only available on 64-bit targets
+// CHECK-32: __builtin_divdeu
+// CHECK-32: error: This builtin is only available on 64-bit targets
+// CHECK-32: __builtin_bpermd
Index: test/CodeGen/builtins-ppc-p7.c
===================================================================
--- test/CodeGen/builtins-ppc-p7.c
+++ test/CodeGen/builtins-ppc-p7.c
@@ -0,0 +1,52 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -target-cpu pwr7 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr8 \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define signext i32 @test_divwe
+int test_divwe(void)
+{
+ int a = 74;
+ int b = 32;
+ return __builtin_divwe(a, b);
+// CHECK @llvm.ppc.divwe
+}
+
+// CHECK-LABEL: define zeroext i32 @test_divweu
+unsigned int test_divweu(void)
+{
+ unsigned int a = 74;
+ unsigned int b = 32;
+ return __builtin_divweu(a, b);
+// CHECK @llvm.ppc.divweu
+}
+
+// CHECK-LABEL: define i64 @test_divde
+long long test_divde(void)
+{
+ long long a = 74LL;
+ long long b = 32LL;
+ return __builtin_divde(a, b);
+// CHECK @llvm.ppc.divde
+}
+
+// CHECK-LABEL: define i64 @test_divdeu
+unsigned long long test_divdeu(void)
+{
+ unsigned long long a = 74ULL;
+ unsigned long long b = 32ULL;
+ return __builtin_divdeu(a, b);
+// CHECK @llvm.ppc.divdeu
+}
+
+// CHECK-LABEL: define i64 @test_bpermd
+long long test_bpermd(void)
+{
+ long long a = 74LL;
+ long long b = 32LL;
+ return __builtin_bpermd(a, b);
+// CHECK @llvm.ppc.bpermd
+}
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits