Index: include/llvm/IR/IntrinsicsPowerPC.td =================================================================== --- include/llvm/IR/IntrinsicsPowerPC.td +++ include/llvm/IR/IntrinsicsPowerPC.td @@ -83,6 +83,12 @@ def int_ppc_fmaf128_round_to_odd : GCCBuiltin<"__builtin_fmaf128_round_to_odd">, Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; + def int_ppc_scalar_extract_expq + : GCCBuiltin<"__builtin_vsx_scalar_extract_expq">, + Intrinsic <[llvm_i64_ty], [llvm_f128_ty], [IntrNoMem]>; + def int_ppc_scalar_insert_exp_qp + : GCCBuiltin<"__builtin_vsx_scalar_insert_exp_qp">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty, llvm_i64_ty], [IntrNoMem]>; } Index: lib/Target/PowerPC/PPCInstrVSX.td =================================================================== --- lib/Target/PowerPC/PPCInstrVSX.td +++ lib/Target/PowerPC/PPCInstrVSX.td @@ -2671,6 +2671,9 @@ def XSIEXPQP : XForm_18<63, 868, (outs vrrc:$vT), (ins vrrc:$vA, vsfrc:$vB), "xsiexpqp $vT, $vA, $vB", IIC_VecFP, []>; + def : Pat<(f128 (int_ppc_scalar_insert_exp_qp f128:$vA, i64:$vB)), + (f128 (XSIEXPQP $vA, (MTVSRD $vB)))>; + // 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", []>; @@ -2678,6 +2681,10 @@ def XSXEXPQP : X_VT5_XO5_VB5 <63, 2, 804, "xsxexpqp", []>; def XSXSIGQP : X_VT5_XO5_VB5 <63, 18, 804, "xsxsigqp", []>; + def : Pat<(i64 (int_ppc_scalar_extract_expq f128:$vA)), + (i64 (MFVSRD (EXTRACT_SUBREG + (v2i64 (XSXEXPQP $vA)), sub_64)))>; + // Vector Insert Word let UseVSXReg = 1 in { // XB NOTE: Only XB.dword[1] is used, but we use vsrc on XB. Index: test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll =================================================================== --- test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll +++ test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll @@ -101,3 +101,39 @@ } declare double @llvm.ppc.truncf128.round.to.odd(fp128) + +; Function Attrs: noinline nounwind optnone +define fp128 @insert_exp_qp(i64 %b) { +entry: + %b.addr = alloca i64, align 8 + store i64 %b, i64* %b.addr, align 8 + %0 = load fp128, fp128* @A, align 16 + %1 = load i64, i64* %b.addr, align 8 + %2 = call fp128 @llvm.ppc.scalar.insert.exp.qp(fp128 %0, i64 %1) + ret fp128 %2 +; CHECK-LABEL: insert_exp_qp +; CHECK: mtvsrd [[FPREG:f[0-9]+]], r3 +; CHECK: lxvx [[VECREG:v[0-9]+]] +; CHECK: xsiexpqp v2, [[VECREG]], [[FPREG]] +; CHECK: blr +} + +; Function Attrs: nounwind readnone +declare fp128 @llvm.ppc.scalar.insert.exp.qp(fp128, i64) + +; Function Attrs: noinline nounwind optnone +define i64 @extract_exp() { +entry: + %0 = load fp128, fp128* @A, align 16 + %1 = call i64 @llvm.ppc.scalar.extract.expq(fp128 %0) + ret i64 %1 +; CHECK-LABEL: extract_exp +; CHECK: lxvx [[VECIN:v[0-9]+]] +; CHECK: xsxexpqp [[VECOUT:v[0-9]+]], [[VECIN]] +; CHECK: mfvsrd r3, [[VECOUT]] +; CHECK: blr +} + +; Function Attrs: nounwind readnone +declare i64 @llvm.ppc.scalar.extract.expq(fp128) +