Index: llvm/trunk/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ llvm/trunk/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -136,17 +136,6 @@ return; } - // For fast-isel, a COPY_TO_REGCLASS may survive this long. This is - // used when converting a 32-bit float to a 64-bit float as part of - // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()), - // as otherwise we have problems with incorrect register classes - // in machine instruction verification. For now, just avoid trying - // to print it as such an instruction has no effect (a 32-bit float - // in a register is already in 64-bit form, just with lower - // precision). FIXME: Is there a better solution? - if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS) - return; - if (!printAliasInstr(MI, O)) printInstruction(MI, O); printAnnotation(O, Annot); Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -105,13 +105,8 @@ void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override { - // For fast-isel, a float COPY_TO_REGCLASS can survive this long. - // It's just a nop to keep the register classes happy, so don't - // generate anything. unsigned Opcode = MI.getOpcode(); const MCInstrDesc &Desc = MCII.get(Opcode); - if (Opcode == TargetOpcode::COPY_TO_REGCLASS) - return; uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); Index: llvm/trunk/lib/Target/PowerPC/PPCFastISel.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCFastISel.cpp +++ llvm/trunk/lib/Target/PowerPC/PPCFastISel.cpp @@ -1131,14 +1131,13 @@ return false; // Convert f32 to f64 if necessary. This is just a meaningless copy - // to get the register class right. COPY_TO_REGCLASS is needed since - // a COPY from F4RC to F8RC is converted to a F4RC-F4RC copy downstream. + // to get the register class right. const TargetRegisterClass *InRC = MRI.getRegClass(SrcReg); if (InRC == &PPC::F4RCRegClass) { unsigned TmpReg = createResultReg(&PPC::F8RCRegClass); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY_TO_REGCLASS), TmpReg) - .addReg(SrcReg).addImm(PPC::F8RCRegClassID); + TII.get(TargetOpcode::COPY), TmpReg) + .addReg(SrcReg); SrcReg = TmpReg; } Index: llvm/trunk/test/CodeGen/PowerPC/fast-isel-fpconv.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/fast-isel-fpconv.ll +++ llvm/trunk/test/CodeGen/PowerPC/fast-isel-fpconv.ll @@ -0,0 +1,33 @@ +; RUN: llc -mtriple powerpc64-unknown-linux-gnu -fast-isel -O0 < %s | FileCheck %s + +; The second fctiwz would use an incorrect input register due to wrong handling +; of COPY_TO_REGCLASS in the FastISel pass. Verify that this is fixed. + +declare void @func(i32, i32) + +define void @test() { +; CHECK-LABEL: test: +; CHECK: bl func +; CHECK-NEXT: nop +; CHECK: lfs [[REG:[0-9]+]], +; CHECK: fctiwz {{[0-9]+}}, [[REG]] +; CHECK: bl func +; CHECK-NEXT: nop + + %memPos = alloca float, align 4 + store float 1.500000e+01, float* %memPos + %valPos = load float, float* %memPos + + %memNeg = alloca float, align 4 + store float -1.500000e+01, float* %memNeg + %valNeg = load float, float* %memNeg + + %FloatToIntPos = fptosi float %valPos to i32 + call void @func(i32 15, i32 %FloatToIntPos) + + %FloatToIntNeg = fptosi float %valNeg to i32 + call void @func(i32 -15, i32 %FloatToIntNeg) + + ret void +} +