llvm.org GIT mirror llvm / ca50bf5
[PowerPC] Remove incorrect use of COPY_TO_REGCLASS in fast isel The fast isel pass currently emits a COPY_TO_REGCLASS node to convert from a F4RC to a F8RC register class during conversion of a floating-point number to integer. There is actually no support in the common code instruction printers to emit COPY_TO_REGCLASS nodes, so the PowerPC back-end has special code there to simply ignore COPY_TO_REGCLASS. This is correct *if and only if* the source and destination registers of COPY_TO_REGCLASS are the same (except for the different register class). But nothing guarantees this to be the case, and if the register allocator does end up allocating source and destination to different registers after all, the back-end simply generates incorrect code. I've included a test case that shows such incorrect code generation. However, it seems that COPY_TO_REGCLASS is actually not intended to be used at the MI layer at all. It is used during SelectionDAG, but always lowered to a plain COPY before emitting MI. Other back-end's fast isel passes never emit COPY_TO_REGCLASS at all. I suspect it is simply wrong for the PowerPC back-end to emit it here. This patch changes the PowerPC back-end to directly emit COPY instead of COPY_TO_REGCLASS and removes the special handling in the instruction printers. Differential Revision: http://reviews.llvm.org/D18605 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265020 91177308-0d34-0410-b5e6-96231b3b80d8 Ulrich Weigand 4 years ago
4 changed file(s) with 36 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
135135 return;
136136 }
137137
138 // For fast-isel, a COPY_TO_REGCLASS may survive this long. This is
139 // used when converting a 32-bit float to a 64-bit float as part of
140 // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()),
141 // as otherwise we have problems with incorrect register classes
142 // in machine instruction verification. For now, just avoid trying
143 // to print it as such an instruction has no effect (a 32-bit float
144 // in a register is already in 64-bit form, just with lower
145 // precision). FIXME: Is there a better solution?
146 if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS)
147 return;
148
149138 if (!printAliasInstr(MI, O))
150139 printInstruction(MI, O);
151140 printAnnotation(O, Annot);
104104 void encodeInstruction(const MCInst &MI, raw_ostream &OS,
105105 SmallVectorImpl &Fixups,
106106 const MCSubtargetInfo &STI) const override {
107 // For fast-isel, a float COPY_TO_REGCLASS can survive this long.
108 // It's just a nop to keep the register classes happy, so don't
109 // generate anything.
110107 unsigned Opcode = MI.getOpcode();
111108 const MCInstrDesc &Desc = MCII.get(Opcode);
112 if (Opcode == TargetOpcode::COPY_TO_REGCLASS)
113 return;
114109
115110 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
116111
11301130 return false;
11311131
11321132 // Convert f32 to f64 if necessary. This is just a meaningless copy
1133 // to get the register class right. COPY_TO_REGCLASS is needed since
1134 // a COPY from F4RC to F8RC is converted to a F4RC-F4RC copy downstream.
1133 // to get the register class right.
11351134 const TargetRegisterClass *InRC = MRI.getRegClass(SrcReg);
11361135 if (InRC == &PPC::F4RCRegClass) {
11371136 unsigned TmpReg = createResultReg(&PPC::F8RCRegClass);
11381137 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1139 TII.get(TargetOpcode::COPY_TO_REGCLASS), TmpReg)
1140 .addReg(SrcReg).addImm(PPC::F8RCRegClassID);
1138 TII.get(TargetOpcode::COPY), TmpReg)
1139 .addReg(SrcReg);
11411140 SrcReg = TmpReg;
11421141 }
11431142
0 ; RUN: llc -mtriple powerpc64-unknown-linux-gnu -fast-isel -O0 < %s | FileCheck %s
1
2 ; The second fctiwz would use an incorrect input register due to wrong handling
3 ; of COPY_TO_REGCLASS in the FastISel pass. Verify that this is fixed.
4
5 declare void @func(i32, i32)
6
7 define void @test() {
8 ; CHECK-LABEL: test:
9 ; CHECK: bl func
10 ; CHECK-NEXT: nop
11 ; CHECK: lfs [[REG:[0-9]+]],
12 ; CHECK: fctiwz {{[0-9]+}}, [[REG]]
13 ; CHECK: bl func
14 ; CHECK-NEXT: nop
15
16 %memPos = alloca float, align 4
17 store float 1.500000e+01, float* %memPos
18 %valPos = load float, float* %memPos
19
20 %memNeg = alloca float, align 4
21 store float -1.500000e+01, float* %memNeg
22 %valNeg = load float, float* %memNeg
23
24 %FloatToIntPos = fptosi float %valPos to i32
25 call void @func(i32 15, i32 %FloatToIntPos)
26
27 %FloatToIntNeg = fptosi float %valNeg to i32
28 call void @func(i32 -15, i32 %FloatToIntNeg)
29
30 ret void
31 }
32