Skip to content

Commit 2aeaaf8

Browse files
Gabriel Hjort Åkerlundmikaelholmen
authored andcommitted
[GlobalISel] Add missing operand update when copy is required
When constraining an operand register using constrainOperandRegClass(), the function may emit a COPY in case the provided register class does not match the current operand register class. However, the operand itself is not updated to make use of the COPY, thereby resulting in incorrect code. This patch fixes that bug by updating the machine operand accordingly. Reviewed By: dsanders Differential Revision: https://reviews.llvm.org/D91244
1 parent b3c260d commit 2aeaaf8

File tree

6 files changed

+33
-45
lines changed

6 files changed

+33
-45
lines changed

llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -527,16 +527,6 @@ class InstructionSelector {
527527
"Subclasses must override this with a tablegen-erated function");
528528
}
529529

530-
/// Constrain a register operand of an instruction \p I to a specified
531-
/// register class. This could involve inserting COPYs before (for uses) or
532-
/// after (for defs) and may replace the operand of \p I.
533-
/// \returns whether operand regclass constraining succeeded.
534-
bool constrainOperandRegToRegClass(MachineInstr &I, unsigned OpIdx,
535-
const TargetRegisterClass &RC,
536-
const TargetInstrInfo &TII,
537-
const TargetRegisterInfo &TRI,
538-
const RegisterBankInfo &RBI) const;
539-
540530
bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
541531
const MachineRegisterInfo &MRI) const;
542532

llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,8 +1058,12 @@ bool InstructionSelector::executeMatchTable(
10581058
int64_t OpIdx = MatchTable[CurrentIdx++];
10591059
int64_t RCEnum = MatchTable[CurrentIdx++];
10601060
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1061-
constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
1062-
*TRI.getRegClass(RCEnum), TII, TRI, RBI);
1061+
MachineInstr &I = *OutMIs[InsnID].getInstr();
1062+
MachineFunction &MF = *I.getParent()->getParent();
1063+
MachineRegisterInfo &MRI = MF.getRegInfo();
1064+
const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum);
1065+
MachineOperand &MO = I.getOperand(OpIdx);
1066+
constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO);
10631067
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
10641068
dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs["
10651069
<< InsnID << "], " << OpIdx << ", " << RCEnum

llvm/include/llvm/CodeGen/GlobalISel/Utils.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ Register constrainRegToClass(MachineRegisterInfo &MRI,
5252

5353
/// Constrain the Register operand OpIdx, so that it is now constrained to the
5454
/// TargetRegisterClass passed as an argument (RegClass).
55-
/// If this fails, create a new virtual register in the correct class and
56-
/// insert a COPY before \p InsertPt if it is a use or after if it is a
57-
/// definition. The debug location of \p InsertPt is used for the new copy.
55+
/// If this fails, create a new virtual register in the correct class and insert
56+
/// a COPY before \p InsertPt if it is a use or after if it is a definition.
57+
/// In both cases, the function also updates the register of RegMo. The debug
58+
/// location of \p InsertPt is used for the new copy.
5859
///
5960
/// \return The virtual register constrained to the right register class.
6061
Register constrainOperandRegClass(const MachineFunction &MF,
@@ -64,12 +65,13 @@ Register constrainOperandRegClass(const MachineFunction &MF,
6465
const RegisterBankInfo &RBI,
6566
MachineInstr &InsertPt,
6667
const TargetRegisterClass &RegClass,
67-
const MachineOperand &RegMO);
68+
MachineOperand &RegMO);
6869

69-
/// Try to constrain Reg so that it is usable by argument OpIdx of the
70-
/// provided MCInstrDesc \p II. If this fails, create a new virtual
71-
/// register in the correct class and insert a COPY before \p InsertPt
72-
/// if it is a use or after if it is a definition.
70+
/// Try to constrain Reg so that it is usable by argument OpIdx of the provided
71+
/// MCInstrDesc \p II. If this fails, create a new virtual register in the
72+
/// correct class and insert a COPY before \p InsertPt if it is a use or after
73+
/// if it is a definition. In both cases, the function also updates the register
74+
/// of RegMo.
7375
/// This is equivalent to constrainOperandRegClass(..., RegClass, ...)
7476
/// with RegClass obtained from the MCInstrDesc. The debug location of \p
7577
/// InsertPt is used for the new copy.
@@ -81,7 +83,7 @@ Register constrainOperandRegClass(const MachineFunction &MF,
8183
const TargetInstrInfo &TII,
8284
const RegisterBankInfo &RBI,
8385
MachineInstr &InsertPt, const MCInstrDesc &II,
84-
const MachineOperand &RegMO, unsigned OpIdx);
86+
MachineOperand &RegMO, unsigned OpIdx);
8587

8688
/// Mutate the newly-selected instruction \p I to constrain its (possibly
8789
/// generic) virtual register operands to the instruction's register class.

llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,6 @@ InstructionSelector::MatcherState::MatcherState(unsigned MaxRenderers)
3333

3434
InstructionSelector::InstructionSelector() = default;
3535

36-
bool InstructionSelector::constrainOperandRegToRegClass(
37-
MachineInstr &I, unsigned OpIdx, const TargetRegisterClass &RC,
38-
const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
39-
const RegisterBankInfo &RBI) const {
40-
MachineBasicBlock &MBB = *I.getParent();
41-
MachineFunction &MF = *MBB.getParent();
42-
MachineRegisterInfo &MRI = MF.getRegInfo();
43-
44-
return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC,
45-
I.getOperand(OpIdx));
46-
}
47-
4836
bool InstructionSelector::isOperandImmEqual(
4937
const MachineOperand &MO, int64_t Value,
5038
const MachineRegisterInfo &MRI) const {

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Register llvm::constrainOperandRegClass(
4848
const MachineFunction &MF, const TargetRegisterInfo &TRI,
4949
MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
5050
const RegisterBankInfo &RBI, MachineInstr &InsertPt,
51-
const TargetRegisterClass &RegClass, const MachineOperand &RegMO) {
51+
const TargetRegisterClass &RegClass, MachineOperand &RegMO) {
5252
Register Reg = RegMO.getReg();
5353
// Assume physical registers are properly constrained.
5454
assert(Register::isVirtualRegister(Reg) && "PhysReg not implemented");
@@ -69,6 +69,13 @@ Register llvm::constrainOperandRegClass(
6969
TII.get(TargetOpcode::COPY), Reg)
7070
.addReg(ConstrainedReg);
7171
}
72+
if (GISelChangeObserver *Observer = MF.getObserver()) {
73+
Observer->changingInstr(*RegMO.getParent());
74+
}
75+
RegMO.setReg(ConstrainedReg);
76+
if (GISelChangeObserver *Observer = MF.getObserver()) {
77+
Observer->changedInstr(*RegMO.getParent());
78+
}
7279
} else {
7380
if (GISelChangeObserver *Observer = MF.getObserver()) {
7481
if (!RegMO.isDef()) {
@@ -86,7 +93,7 @@ Register llvm::constrainOperandRegClass(
8693
const MachineFunction &MF, const TargetRegisterInfo &TRI,
8794
MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
8895
const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II,
89-
const MachineOperand &RegMO, unsigned OpIdx) {
96+
MachineOperand &RegMO, unsigned OpIdx) {
9097
Register Reg = RegMO.getReg();
9198
// Assume physical registers are properly constrained.
9299
assert(Register::isVirtualRegister(Reg) && "PhysReg not implemented");
@@ -156,8 +163,7 @@ bool llvm::constrainSelectedInstRegOperands(MachineInstr &I,
156163
// If the operand is a vreg, we should constrain its regclass, and only
157164
// insert COPYs if that's impossible.
158165
// constrainOperandRegClass does that for us.
159-
MO.setReg(constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(),
160-
MO, OpI));
166+
constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(), MO, OpI);
161167

162168
// Tie uses to defs as indicated in MCInstrDesc if this hasn't already been
163169
// done.

llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -933,10 +933,9 @@ bool AArch64CallLowering::lowerTailCall(
933933
// If Callee is a reg, since it is used by a target specific instruction,
934934
// it must have a register class matching the constraint of that instruction.
935935
if (Info.Callee.isReg())
936-
MIB->getOperand(0).setReg(constrainOperandRegClass(
937-
MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
938-
*MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Info.Callee,
939-
0));
936+
constrainOperandRegClass(MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
937+
*MF.getSubtarget().getRegBankInfo(), *MIB,
938+
MIB->getDesc(), Info.Callee, 0);
940939

941940
MF.getFrameInfo().setHasTailCall();
942941
Info.LoweredTailCall = true;
@@ -1018,10 +1017,9 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
10181017
// instruction, it must have a register class matching the
10191018
// constraint of that instruction.
10201019
if (Info.Callee.isReg())
1021-
MIB->getOperand(0).setReg(constrainOperandRegClass(
1022-
MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
1023-
*MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Info.Callee,
1024-
0));
1020+
constrainOperandRegClass(MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
1021+
*MF.getSubtarget().getRegBankInfo(), *MIB,
1022+
MIB->getDesc(), Info.Callee, 0);
10251023

10261024
// Finally we can copy the returned value back into its virtual-register. In
10271025
// symmetry with the arguments, the physical register must be an

0 commit comments

Comments
 (0)