Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -12282,6 +12282,13 @@ bool ValidTypeForStoreFltAsInt = (Op1VT == MVT::i32) || (Subtarget.hasP9Vector() && (Op1VT == MVT::i8 || Op1VT == MVT::i16)); + // STORE (FP_TO_SINT MVT::f128) is legal. + if (N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && + ValidTypeForStoreFltAsInt && + N->getOperand(1).getOperand(0).getValueType() == MVT::f128) { + return SDValue(); + } + // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). if (Subtarget.hasSTFIWX() && !cast(N)->isTruncatingStore() && N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && Index: lib/Target/PowerPC/PPCInstrVSX.td =================================================================== --- lib/Target/PowerPC/PPCInstrVSX.td +++ lib/Target/PowerPC/PPCInstrVSX.td @@ -1259,6 +1259,9 @@ "stxsspx $XT, $dst", IIC_LdStSTFD, []>; def STXSIWX : XX1Form_memOp<31, 140, (outs), (ins vsfrc:$XT, memrr:$dst), "stxsiwx $XT, $dst", IIC_LdStSTFD, []>; + let isCodeGenOnly = 1 in + def STXSIWXq : XX1Form<31, 140, (outs), (ins vrrc:$XT, memrr:$dst), + "stxsiwx $XT, $dst", IIC_LdStSTFD, []>; // Please note let isPseudo = 1 is not part of class Pseudo<>. Missing it // would cause these Pseudos are not expanded in expandPostRAPseudos() @@ -2509,10 +2512,14 @@ def : Pat<(i64 (fp_to_sint f128:$src)), (i64 (MFVRD (XSCVQPSDZ $src)))>; def XSCVQPSWZ : X_VT5_XO5_VB5<63, 9, 836, "xscvqpswz", []>; + def : Pat<(i32 (fp_to_sint f128:$src)), + (i32 (MFVSRWZ (COPY_TO_REGCLASS (XSCVQPSWZ $src), VFRC)))>; def XSCVQPUDZ : X_VT5_XO5_VB5<63, 17, 836, "xscvqpudz", []>; def : Pat<(i64 (fp_to_uint f128:$src)), (i64 (MFVRD (XSCVQPUDZ $src)))>; def XSCVQPUWZ : X_VT5_XO5_VB5<63, 1, 836, "xscvqpuwz", []>; + def : Pat<(i32 (fp_to_uint f128:$src)), + (i32 (MFVSRWZ (COPY_TO_REGCLASS (XSCVQPUWZ $src), VFRC)))>; // Convert (Un)Signed DWord -> QP def XSCVSDQP : X_VT5_XO5_VB5_TyVB<63, 10, 836, "xscvsdqp", vfrc, []>; @@ -3159,6 +3166,12 @@ (STXSD (COPY_TO_REGCLASS (XSCVQPSDZ $src), VFRC), xoaddr:$dst)>; def : Pat<(store (i64 (fp_to_uint f128:$src)), xoaddr:$dst), (STXSD (COPY_TO_REGCLASS (XSCVQPUDZ $src), VFRC), xoaddr:$dst)>; + def : Pat<(store (i32 (fp_to_sint f128:$src)), xoaddr:$dst), + //(STXSIWX (COPY_TO_REGCLASS (XSCVQPSWZ $src), VSRC), xoaddr:$dst)>; + (STXSIWXq (XSCVQPSWZ $src), xoaddr:$dst)>; + def : Pat<(store (i32 (fp_to_uint f128:$src)), xoaddr:$dst), + //(STXSIWXq (COPY_TO_REGCLASS (XSCVQPUWZ $src), VSRC), xoaddr:$dst)>; + (STXSIWXq (XSCVQPUWZ $src), xoaddr:$dst)>; } // end HasP9Vector, AddedComplexity Index: test/CodeGen/PowerPC/f128-truncateNconv.ll =================================================================== --- test/CodeGen/PowerPC/f128-truncateNconv.ll +++ test/CodeGen/PowerPC/f128-truncateNconv.ll @@ -156,3 +156,155 @@ ; CHECK-NEXT: stxsd [[CONV]], 0(5) ; CHECK-NEXT: blr } + +; Function Attrs: norecurse nounwind readonly +define signext i32 @qpConv2sw(fp128* nocapture readonly %a) { +entry: + %0 = load fp128, fp128* %a, align 16 + %conv = fptosi fp128 %0 to i32 + ret i32 %conv + +; CHECK-LABEL: qpConv2sw +; CHECK: lxv [[REG:[0-9]+]], 0(3) +; CHECK-NEXT: xscvqpswz [[CONV:[0-9]+]], [[REG]] +; CHECK-NEXT: mfvsrwz [[REG2:[0-9]+]], [[CONV]] +; CHECK-NEXT: extsw 3, [[REG2]] +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind +define void @qpConv2sw_02(i32* nocapture %res) { +entry: + %0 = load fp128, fp128* getelementptr inbounds + ([4 x fp128], [4 x fp128]* @f128Array, i64 0, + i64 2), align 16 + %conv = fptosi fp128 %0 to i32 + store i32 %conv, i32* %res, align 4 + ret void + +; CHECK-LABEL: qpConv2sw_02 +; CHECK: addis [[REG0:[0-9]+]], 2, .LC0@toc@ha +; CHECK: ld [[REG0]], .LC0@toc@l([[REG0]]) +; CHECK: lxv [[REG:[0-9]+]], 32([[REG0]]) +; CHECK-NEXT: xscvqpswz [[CONV:[0-9]+]], [[REG]] +; CHECK-NEXT: stxsiwx [[CONV]], 0, 3 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readonly +define signext i32 @qpConv2sw_03(fp128* nocapture readonly %a) { +entry: + %0 = load fp128, fp128* %a, align 16 + %1 = load fp128, fp128* getelementptr inbounds + ([4 x fp128], [4 x fp128]* @f128Array, i64 0, + i64 1), align 16 + %add = fadd fp128 %0, %1 + %conv = fptosi fp128 %add to i32 + ret i32 %conv + +; CHECK-LABEL: qpConv2sw_03 +; CHECK: addis [[REG0:[0-9]+]], 2, .LC0@toc@ha +; CHECK-DAG: ld [[REG0]], .LC0@toc@l([[REG0]]) +; CHECK-DAG: lxv [[REG1:[0-9]+]], 16([[REG0]]) +; CHECK-DAG: lxv [[REG:[0-9]+]], 0(3) +; CHECK-NEXT: xsaddqp [[ADD:[0-9]+]], [[REG]], [[REG1]] +; CHECK-NEXT: xscvqpswz [[CONV:[0-9]+]], [[ADD]] +; CHECK-NEXT: mfvsrwz [[REG2:[0-9]+]], [[CONV]] +; CHECK-NEXT: extsw 3, [[REG2]] +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind +define void @qpConv2sw_04(fp128* nocapture readonly %a, + fp128* nocapture readonly %b, i32* nocapture %res) { +entry: + %0 = load fp128, fp128* %a, align 16 + %1 = load fp128, fp128* %b, align 16 + %add = fadd fp128 %0, %1 + %conv = fptosi fp128 %add to i32 + store i32 %conv, i32* %res, align 4 + ret void + +; CHECK-LABEL: qpConv2sw_04 +; CHECK-DAG: lxv [[REG1:[0-9]+]], 0(4) +; CHECK-DAG: lxv [[REG:[0-9]+]], 0(3) +; CHECK-NEXT: xsaddqp [[ADD:[0-9]+]], [[REG]], [[REG1]] +; CHECK-NEXT: xscvqpswz [[CONV:[0-9]+]], [[ADD]] +; CHECK-NEXT: stxsiwx [[CONV]], 0, 5 +; CHECK-NEXT: blr +} + +; Function Attrs: norecurse nounwind readonly +define zeroext i32 @qpConv2uw(fp128* nocapture readonly %a) { +entry: + %0 = load fp128, fp128* %a, align 16 + %conv = fptoui fp128 %0 to i32 + ret i32 %conv + +; CHECK-LABEL: qpConv2uw +; CHECK: lxv [[REG:[0-9]+]], 0(3) +; CHECK-NEXT: xscvqpuwz [[CONV:[0-9]+]], [[ADD]] +; CHECK-NEXT: mfvsrwz 3, [[CONV]] +; CHECK: blr +} + +; Function Attrs: norecurse nounwind +define void @qpConv2uw_02(i32* nocapture %res) { +entry: + %0 = load fp128, fp128* getelementptr inbounds + ([4 x fp128], [4 x fp128]* @f128Array, i64 0, + i64 2), align 16 + %conv = fptoui fp128 %0 to i32 + store i32 %conv, i32* %res, align 4 + ret void + +; CHECK-LABEL: qpConv2uw_02 +; CHECK: addis [[REG0:[0-9]+]], 2, .LC0@toc@ha +; CHECK: ld [[REG0]], .LC0@toc@l([[REG0]]) +; CHECK: lxv [[REG:[0-9]+]], 32([[REG0]]) +; CHECK-NEXT: xscvqpuwz [[CONV:[0-9]+]], [[ADD]] +; CHECK-NEXT: stxsiwx [[CONV]], 0, 3 +; CHECK: blr +} + +; Function Attrs: norecurse nounwind readonly +define zeroext i32 @qpConv2uw_03(fp128* nocapture readonly %a) { +entry: + %0 = load fp128, fp128* %a, align 16 + %1 = load fp128, fp128* getelementptr inbounds + ([4 x fp128], [4 x fp128]* @f128Array, i64 0, + i64 1), align 16 + %add = fadd fp128 %0, %1 + %conv = fptoui fp128 %add to i32 + ret i32 %conv + +; CHECK-LABEL: qpConv2uw_03 +; CHECK: addis [[REG0:[0-9]+]], 2, .LC0@toc@ha +; CHECK-DAG: ld [[REG0]], .LC0@toc@l([[REG0]]) +; CHECK-DAG: lxv [[REG1:[0-9]+]], 16([[REG0]]) +; CHECK-DAG: lxv [[REG:[0-9]+]], 0(3) +; CHECK-NEXT: xsaddqp [[ADD:[0-9]+]], [[REG]], [[REG1]] +; CHECK-NEXT: xscvqpuwz [[CONV:[0-9]+]], [[ADD]] +; CHECK-NEXT: mfvsrwz 3, [[CONV]] +; CHECK: blr +} + +; Function Attrs: norecurse nounwind +define void @qpConv2uw_04(fp128* nocapture readonly %a, + fp128* nocapture readonly %b, i32* nocapture %res) { +entry: + %0 = load fp128, fp128* %a, align 16 + %1 = load fp128, fp128* %b, align 16 + %add = fadd fp128 %0, %1 + %conv = fptoui fp128 %add to i32 + store i32 %conv, i32* %res, align 4 + ret void + +; CHECK-LABEL: qpConv2uw_04 +; CHECK-DAG: lxv [[REG1:[0-9]+]], 0(4) +; CHECK-DAG: lxv [[REG:[0-9]+]], 0(3) +; CHECK-NEXT: xsaddqp [[ADD:[0-9]+]], [[REG]], [[REG1]] +; CHECK-NEXT: xscvqpuwz [[CONV:[0-9]+]], [[ADD]] +; CHECK-NEXT: stxsiwx [[CONV]], 0, 5 +; CHECK: blr +}