forked from OSchip/llvm-project
GlobalISel: perform multi-step legalization
llvm-svn: 279758
This commit is contained in:
parent
2c4a838e24
commit
438c77ca1a
|
@ -21,6 +21,8 @@
|
||||||
#include "llvm/CodeGen/LowLevelType.h"
|
#include "llvm/CodeGen/LowLevelType.h"
|
||||||
#include "llvm/IR/DebugLoc.h"
|
#include "llvm/IR/DebugLoc.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
|
@ -47,6 +49,8 @@ class MachineIRBuilder {
|
||||||
bool Before;
|
bool Before;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
std::function<void(MachineInstr *)> InsertedInstr;
|
||||||
|
|
||||||
const TargetInstrInfo &getTII() {
|
const TargetInstrInfo &getTII() {
|
||||||
assert(TII && "TargetInstrInfo is not set");
|
assert(TII && "TargetInstrInfo is not set");
|
||||||
return *TII;
|
return *TII;
|
||||||
|
@ -86,6 +90,13 @@ public:
|
||||||
void setInstr(MachineInstr &MI, bool Before = true);
|
void setInstr(MachineInstr &MI, bool Before = true);
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/// Control where instructions we create are recorded (typically for
|
||||||
|
/// visiting again later during legalization).
|
||||||
|
/// @{
|
||||||
|
void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr);
|
||||||
|
void stopRecordingInsertions();
|
||||||
|
/// @}
|
||||||
|
|
||||||
/// Set the debug location to \p DL for all the next build instructions.
|
/// Set the debug location to \p DL for all the next build instructions.
|
||||||
void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
|
void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,9 @@ public:
|
||||||
///
|
///
|
||||||
/// Considered as an opaque blob, the legal code will use and define the same
|
/// Considered as an opaque blob, the legal code will use and define the same
|
||||||
/// registers as \p MI.
|
/// registers as \p MI.
|
||||||
|
LegalizeResult legalizeInstrStep(MachineInstr &MI,
|
||||||
|
const MachineLegalizer &Legalizer);
|
||||||
|
|
||||||
LegalizeResult legalizeInstr(MachineInstr &MI,
|
LegalizeResult legalizeInstr(MachineInstr &MI,
|
||||||
const MachineLegalizer &Legalizer);
|
const MachineLegalizer &Legalizer);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ void MachineIRBuilder::setMF(MachineFunction &MF) {
|
||||||
this->TII = MF.getSubtarget().getInstrInfo();
|
this->TII = MF.getSubtarget().getInstrInfo();
|
||||||
this->DL = DebugLoc();
|
this->DL = DebugLoc();
|
||||||
this->MI = nullptr;
|
this->MI = nullptr;
|
||||||
|
this->InsertedInstr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MachineIRBuilder::setMBB(MachineBasicBlock &MBB, bool Beginning) {
|
void MachineIRBuilder::setMBB(MachineBasicBlock &MBB, bool Beginning) {
|
||||||
|
@ -53,6 +54,15 @@ MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() {
|
||||||
return Before ? getMBB().begin() : getMBB().end();
|
return Before ? getMBB().begin() : getMBB().end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MachineIRBuilder::recordInsertions(
|
||||||
|
std::function<void(MachineInstr *)> Inserted) {
|
||||||
|
InsertedInstr = Inserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineIRBuilder::stopRecordingInsertions() {
|
||||||
|
InsertedInstr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Build instruction variants.
|
// Build instruction variants.
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -69,6 +79,8 @@ MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opcode,
|
||||||
assert(!isPreISelGenericOpcode(Opcode) &&
|
assert(!isPreISelGenericOpcode(Opcode) &&
|
||||||
"Generic instruction must have a type");
|
"Generic instruction must have a type");
|
||||||
getMBB().insert(getInsertPt(), MIB);
|
getMBB().insert(getInsertPt(), MIB);
|
||||||
|
if (InsertedInstr)
|
||||||
|
InsertedInstr(MIB);
|
||||||
return MIB;
|
return MIB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +193,8 @@ MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<LLT> ResTys,
|
||||||
MIB.addImm(Idx);
|
MIB.addImm(Idx);
|
||||||
|
|
||||||
getMBB().insert(getInsertPt(), MIB);
|
getMBB().insert(getInsertPt(), MIB);
|
||||||
|
if (InsertedInstr)
|
||||||
|
InsertedInstr(MIB);
|
||||||
|
|
||||||
return MIB;
|
return MIB;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,9 @@ MachineLegalizeHelper::MachineLegalizeHelper(MachineFunction &MF)
|
||||||
MIRBuilder.setMF(MF);
|
MIRBuilder.setMF(MF);
|
||||||
}
|
}
|
||||||
|
|
||||||
MachineLegalizeHelper::LegalizeResult MachineLegalizeHelper::legalizeInstr(
|
MachineLegalizeHelper::LegalizeResult
|
||||||
MachineInstr &MI, const MachineLegalizer &Legalizer) {
|
MachineLegalizeHelper::legalizeInstrStep(MachineInstr &MI,
|
||||||
|
const MachineLegalizer &Legalizer) {
|
||||||
auto Action = Legalizer.getAction(MI);
|
auto Action = Legalizer.getAction(MI);
|
||||||
switch (std::get<0>(Action)) {
|
switch (std::get<0>(Action)) {
|
||||||
case MachineLegalizer::Legal:
|
case MachineLegalizer::Legal:
|
||||||
|
@ -48,6 +49,30 @@ MachineLegalizeHelper::LegalizeResult MachineLegalizeHelper::legalizeInstr(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachineLegalizeHelper::LegalizeResult
|
||||||
|
MachineLegalizeHelper::legalizeInstr(MachineInstr &MI,
|
||||||
|
const MachineLegalizer &Legalizer) {
|
||||||
|
std::queue<MachineInstr *> WorkList;
|
||||||
|
MIRBuilder.recordInsertions([&](MachineInstr *MI) { WorkList.push(MI); });
|
||||||
|
WorkList.push(&MI);
|
||||||
|
|
||||||
|
bool Changed = false;
|
||||||
|
LegalizeResult Res;
|
||||||
|
do {
|
||||||
|
Res = legalizeInstrStep(*WorkList.front(), Legalizer);
|
||||||
|
if (Res == UnableToLegalize) {
|
||||||
|
MIRBuilder.stopRecordingInsertions();
|
||||||
|
return UnableToLegalize;
|
||||||
|
}
|
||||||
|
Changed |= Res == Legalized;
|
||||||
|
WorkList.pop();
|
||||||
|
} while (!WorkList.empty());
|
||||||
|
|
||||||
|
MIRBuilder.stopRecordingInsertions();
|
||||||
|
|
||||||
|
return Changed ? Legalized : AlreadyLegal;
|
||||||
|
}
|
||||||
|
|
||||||
void MachineLegalizeHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
|
void MachineLegalizeHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
|
||||||
SmallVectorImpl<unsigned> &VRegs) {
|
SmallVectorImpl<unsigned> &VRegs) {
|
||||||
unsigned Size = Ty.getSizeInBits();
|
unsigned Size = Ty.getSizeInBits();
|
||||||
|
|
|
@ -48,6 +48,10 @@ AArch64MachineLegalizer::AArch64MachineLegalizer() {
|
||||||
for (auto Ty : {s32, s64})
|
for (auto Ty : {s32, s64})
|
||||||
setAction({BinOp, Ty}, Legal);
|
setAction({BinOp, Ty}, Legal);
|
||||||
|
|
||||||
|
for (auto Op : { G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULO, G_UMULO })
|
||||||
|
for (auto Ty : { s32, s64 })
|
||||||
|
setAction({Op, Ty}, Legal);
|
||||||
|
|
||||||
for (auto BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
|
for (auto BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
|
||||||
for (auto Ty : {s32, s64})
|
for (auto Ty : {s32, s64})
|
||||||
setAction({BinOp, Ty}, Legal);
|
setAction({BinOp, Ty}, Legal);
|
||||||
|
@ -99,6 +103,20 @@ AArch64MachineLegalizer::AArch64MachineLegalizer() {
|
||||||
setAction({G_ANYEXT, 1, Ty}, Legal);
|
setAction({G_ANYEXT, 1, Ty}, Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Truncations
|
||||||
|
for (auto Ty : { s16, s32 })
|
||||||
|
setAction({G_FPTRUNC, Ty}, Legal);
|
||||||
|
|
||||||
|
for (auto Ty : { s32, s64 })
|
||||||
|
setAction({G_FPTRUNC, 1, Ty}, Legal);
|
||||||
|
|
||||||
|
for (auto Ty : { s1, s8, s16, s32 })
|
||||||
|
setAction({G_TRUNC, Ty}, Legal);
|
||||||
|
|
||||||
|
for (auto Ty : { s8, s16, s32, s64 })
|
||||||
|
setAction({G_TRUNC, 1, Ty}, Legal);
|
||||||
|
|
||||||
|
|
||||||
// Control-flow
|
// Control-flow
|
||||||
setAction({G_BR, LLT::unsized()}, Legal);
|
setAction({G_BR, LLT::unsized()}, Legal);
|
||||||
setAction({G_BRCOND, s32}, Legal);
|
setAction({G_BRCOND, s32}, Legal);
|
||||||
|
|
|
@ -29,7 +29,8 @@ body: |
|
||||||
; CHECK-LABEL: name: test_scalar_add_big
|
; CHECK-LABEL: name: test_scalar_add_big
|
||||||
; CHECK-DAG: [[LHS_LO:%.*]](64), [[LHS_HI:%.*]](64) = G_EXTRACT { s64, s64, s128 } %0, 0, 64
|
; CHECK-DAG: [[LHS_LO:%.*]](64), [[LHS_HI:%.*]](64) = G_EXTRACT { s64, s64, s128 } %0, 0, 64
|
||||||
; CHECK-DAG: [[RHS_LO:%.*]](64), [[RHS_HI:%.*]](64) = G_EXTRACT { s64, s64, s128 } %1, 0, 64
|
; CHECK-DAG: [[RHS_LO:%.*]](64), [[RHS_HI:%.*]](64) = G_EXTRACT { s64, s64, s128 } %1, 0, 64
|
||||||
; CHECK-DAG: [[CARRY0:%.*]](1) = G_CONSTANT s1 0
|
; CHECK-DAG: [[CARRY0_32:%.*]](32) = G_CONSTANT s32 0
|
||||||
|
; CHECK-DAG: [[CARRY0:%[0-9]+]](1) = G_TRUNC { s1, s32 } [[CARRY0_32]]
|
||||||
; CHECK: [[RES_LO:%.*]](64), [[CARRY:%.*]](1) = G_UADDE s64 [[LHS_LO]], [[RHS_LO]], [[CARRY0]]
|
; CHECK: [[RES_LO:%.*]](64), [[CARRY:%.*]](1) = G_UADDE s64 [[LHS_LO]], [[RHS_LO]], [[CARRY0]]
|
||||||
; CHECK: [[RES_HI:%.*]](64), {{%.*}}(1) = G_UADDE s64 [[LHS_HI]], [[RHS_HI]], [[CARRY]]
|
; CHECK: [[RES_HI:%.*]](64), {{%.*}}(1) = G_UADDE s64 [[LHS_HI]], [[RHS_HI]], [[CARRY]]
|
||||||
; CHECK: %2(128) = G_SEQUENCE { s128, s64, s64 } [[RES_LO]], 0, [[RES_HI]], 64
|
; CHECK: %2(128) = G_SEQUENCE { s128, s64, s64 } [[RES_LO]], 0, [[RES_HI]], 64
|
||||||
|
|
|
@ -20,6 +20,7 @@ registers:
|
||||||
- { id: 5, class: _ }
|
- { id: 5, class: _ }
|
||||||
- { id: 6, class: _ }
|
- { id: 6, class: _ }
|
||||||
- { id: 7, class: _ }
|
- { id: 7, class: _ }
|
||||||
|
- { id: 8, class: _ }
|
||||||
body: |
|
body: |
|
||||||
bb.0.entry:
|
bb.0.entry:
|
||||||
liveins: %x0, %x1, %x2, %x3
|
liveins: %x0, %x1, %x2, %x3
|
||||||
|
@ -48,4 +49,9 @@ body: |
|
||||||
; CHECK: %7(32) = G_ICMP { s32, s32 } intpred(sle), [[LHS32]], [[RHS32]]
|
; CHECK: %7(32) = G_ICMP { s32, s32 } intpred(sle), [[LHS32]], [[RHS32]]
|
||||||
%7(32) = G_ICMP { s32, s8 } intpred(sle), %2, %3
|
%7(32) = G_ICMP { s32, s8 } intpred(sle), %2, %3
|
||||||
|
|
||||||
|
; CHECK: [[LHS32:%[0-9]+]](32) = G_ZEXT { s32, s8 } %2
|
||||||
|
; CHECK: [[RHS32:%[0-9]+]](32) = G_ZEXT { s32, s8 } %3
|
||||||
|
; CHECK: [[TST32:%[0-9]+]](32) = G_ICMP { s32, s32 } intpred(ult), [[LHS32]], [[RHS32]]
|
||||||
|
; CHECK: %8(1) = G_TRUNC { s1, s32 } [[TST32]]
|
||||||
|
%8(1) = G_ICMP { s1, s8 } intpred(ult), %2, %3
|
||||||
...
|
...
|
||||||
|
|
Loading…
Reference in New Issue