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 +} +