Files
clang-p2996/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
Tim Northover 26b76f2c59 GlobalISel: improve representation of G_SEQUENCE and G_EXTRACT
First, make sure all types involved are represented, rather than being implicit
from the register width.

Second, canonicalize all types to scalar. These operations just act in bits and
don't care about vectors.

Also standardize spelling of Indices in the MachineIRBuilder (NFC here).

llvm-svn: 279294
2016-08-19 18:32:14 +00:00

170 lines
5.7 KiB
C++

//===-- llvm/CodeGen/GlobalISel/MachineLegalizeHelper.cpp -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file This file implements the MachineLegalizeHelper class to legalize
/// individual instructions and the LegalizeMachineIR wrapper pass for the
/// primary legalization.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h"
#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <sstream>
#define DEBUG_TYPE "legalize-mir"
using namespace llvm;
MachineLegalizeHelper::MachineLegalizeHelper(MachineFunction &MF)
: MRI(MF.getRegInfo()) {
MIRBuilder.setMF(MF);
}
MachineLegalizeHelper::LegalizeResult MachineLegalizeHelper::legalizeInstr(
MachineInstr &MI, const MachineLegalizer &Legalizer) {
auto Action = Legalizer.getAction(MI);
switch (Action.first) {
case MachineLegalizer::Legal:
return AlreadyLegal;
case MachineLegalizer::NarrowScalar:
return narrowScalar(MI, Action.second);
case MachineLegalizer::WidenScalar:
return widenScalar(MI, Action.second);
case MachineLegalizer::FewerElements:
return fewerElementsVector(MI, Action.second);
default:
return UnableToLegalize;
}
}
void MachineLegalizeHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
SmallVectorImpl<unsigned> &VRegs) {
unsigned Size = Ty.getSizeInBits();
SmallVector<uint64_t, 4> Indexes;
SmallVector<LLT, 4> ResTys;
for (int i = 0; i < NumParts; ++i) {
VRegs.push_back(MRI.createGenericVirtualRegister(Size));
Indexes.push_back(i * Size);
ResTys.push_back(Ty);
}
MIRBuilder.buildExtract(ResTys, VRegs, Indexes,
LLT::scalar(Ty.getSizeInBits() * NumParts), Reg);
}
MachineLegalizeHelper::LegalizeResult
MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) {
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_ADD: {
// Expand in terms of carry-setting/consuming G_ADDE instructions.
unsigned NarrowSize = NarrowTy.getSizeInBits();
int NumParts = MI.getType().getSizeInBits() / NarrowSize;
MIRBuilder.setInstr(MI);
SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs, Indexes;
extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
unsigned CarryIn = MRI.createGenericVirtualRegister(1);
MIRBuilder.buildConstant(LLT::scalar(1), CarryIn, 0);
SmallVector<LLT, 2> DstTys;
for (int i = 0; i < NumParts; ++i) {
unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
unsigned CarryOut = MRI.createGenericVirtualRegister(1);
MIRBuilder.buildUAdde(NarrowTy, DstReg, CarryOut, Src1Regs[i],
Src2Regs[i], CarryIn);
DstTys.push_back(NarrowTy);
DstRegs.push_back(DstReg);
Indexes.push_back(i * NarrowSize);
CarryIn = CarryOut;
}
MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstTys,
DstRegs, Indexes);
MI.eraseFromParent();
return Legalized;
}
}
}
MachineLegalizeHelper::LegalizeResult
MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) {
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_ADD:
case TargetOpcode::G_AND:
case TargetOpcode::G_MUL:
case TargetOpcode::G_OR:
case TargetOpcode::G_XOR:
case TargetOpcode::G_SUB: {
// Perform operation at larger width (any extension is fine here, high bits
// don't affect the result) and then truncate the result back to the
// original type.
unsigned WideSize = WideTy.getSizeInBits();
MIRBuilder.setInstr(MI);
unsigned Src1Ext = MRI.createGenericVirtualRegister(WideSize);
unsigned Src2Ext = MRI.createGenericVirtualRegister(WideSize);
MIRBuilder.buildAnyExtend(WideTy, Src1Ext, MI.getOperand(1).getReg());
MIRBuilder.buildAnyExtend(WideTy, Src2Ext, MI.getOperand(2).getReg());
unsigned DstExt = MRI.createGenericVirtualRegister(WideSize);
MIRBuilder.buildInstr(MI.getOpcode(), WideTy)
.addDef(DstExt).addUse(Src1Ext).addUse(Src2Ext);
MIRBuilder.buildTrunc(MI.getType(), MI.getOperand(0).getReg(), DstExt);
MI.eraseFromParent();
return Legalized;
}
}
}
MachineLegalizeHelper::LegalizeResult
MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, LLT NarrowTy) {
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_ADD: {
unsigned NarrowSize = NarrowTy.getSizeInBits();
int NumParts = MI.getType().getSizeInBits() / NarrowSize;
MIRBuilder.setInstr(MI);
SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs, Indexes;
extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
SmallVector<LLT, 2> DstTys;
for (int i = 0; i < NumParts; ++i) {
unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
MIRBuilder.buildAdd(NarrowTy, DstReg, Src1Regs[i], Src2Regs[i]);
DstTys.push_back(NarrowTy);
DstRegs.push_back(DstReg);
Indexes.push_back(i * NarrowSize);
}
MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstTys,
DstRegs, Indexes);
MI.eraseFromParent();
return Legalized;
}
}
}