1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

GlobalISel: legalize sdiv and srem operations.

llvm-svn: 279842
This commit is contained in:
Tim Northover 2016-08-26 17:46:13 +00:00
parent 94b2dc6476
commit a9938048f7
9 changed files with 134 additions and 0 deletions

View File

@ -144,6 +144,28 @@ public:
MachineInstrBuilder buildAdd(LLT Ty, unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def> = G_SUB \p Ty \p Op0, \p Op1
///
/// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
/// truncated to their width.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildSub(LLT Ty, unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def> = G_MUL \p Ty \p Op0, \p Op1
///
/// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
/// truncated to their width.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildMul(LLT Ty, unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def>, \p CarryOut = G_UADDE \p Tys \p Op0, \p Op1,
/// \p CarryIn
///

View File

@ -70,6 +70,10 @@ public:
/// precision, ignoring the unused bits).
LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
/// Legalize an instruction by splitting it into simpler parts, hopefully
/// understood by the target.
LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
/// Legalize a vector instruction by splitting into multiple components, each
/// acting on the same scalar type as the original but with fewer elements.
LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,

View File

@ -87,6 +87,10 @@ public:
/// the first two results.
MoreElements,
/// The operation itself must be expressed in terms of simpler actions on
/// this target. E.g. a SREM replaced by an SDIV and subtraction.
Lower,
/// The operation should be implemented as a call to some kind of runtime
/// support library. For example this usually happens on machines that don't
/// support floating-point operations natively.

View File

@ -99,6 +99,22 @@ MachineInstrBuilder MachineIRBuilder::buildAdd(LLT Ty, unsigned Res,
.addUse(Op1);
}
MachineInstrBuilder MachineIRBuilder::buildSub(LLT Ty, unsigned Res,
unsigned Op0, unsigned Op1) {
return buildInstr(TargetOpcode::G_SUB, Ty)
.addDef(Res)
.addUse(Op0)
.addUse(Op1);
}
MachineInstrBuilder MachineIRBuilder::buildMul(LLT Ty, unsigned Res,
unsigned Op0, unsigned Op1) {
return buildInstr(TargetOpcode::G_MUL, Ty)
.addDef(Res)
.addUse(Op0)
.addUse(Op1);
}
MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
return buildInstr(TargetOpcode::G_BR, LLT::unsized()).addMBB(&Dest);
}

View File

@ -42,6 +42,8 @@ MachineLegalizeHelper::legalizeInstrStep(MachineInstr &MI,
return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
case MachineLegalizer::WidenScalar:
return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
case MachineLegalizer::Lower:
return lower(MI, std::get<1>(Action), std::get<2>(Action));
case MachineLegalizer::FewerElements:
return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
default:
@ -268,6 +270,33 @@ MachineLegalizeHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx,
}
}
MachineLegalizeHelper::LegalizeResult
MachineLegalizeHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
using namespace TargetOpcode;
unsigned Size = Ty.getSizeInBits();
MIRBuilder.setInstr(MI);
switch(MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_SREM:
case TargetOpcode::G_UREM: {
unsigned QuotReg = MRI.createGenericVirtualRegister(Size);
MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, Ty)
.addDef(QuotReg)
.addUse(MI.getOperand(1).getReg())
.addUse(MI.getOperand(2).getReg());
unsigned ProdReg = MRI.createGenericVirtualRegister(Size);
MIRBuilder.buildMul(Ty, ProdReg, QuotReg, MI.getOperand(2).getReg());
MIRBuilder.buildSub(Ty, MI.getOperand(0).getReg(),
MI.getOperand(1).getReg(), ProdReg);
MI.eraseFromParent();
return Legalized;
}
}
}
MachineLegalizeHelper::LegalizeResult
MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
LLT NarrowTy) {

View File

@ -126,6 +126,7 @@ LLT MachineLegalizer::findLegalType(const InstrAspect &Aspect,
default:
llvm_unreachable("Cannot find legal type");
case Legal:
case Lower:
return Aspect.Type;
case NarrowScalar: {
return findLegalType(Aspect,

View File

@ -51,6 +51,10 @@ AArch64MachineLegalizer::AArch64MachineLegalizer() {
setAction({BinOp, Ty}, WidenScalar);
}
for (auto BinOp : { G_SREM, G_UREM })
for (auto Ty : { s1, s8, s16, s32, s64 })
setAction({BinOp, Ty}, Lower);
for (auto Op : { G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULO, G_UMULO }) {
for (auto Ty : { s32, s64 })
setAction({Op, Ty}, Legal);

View File

@ -0,0 +1,52 @@
# RUN: llc -O0 -run-pass=legalize-mir -global-isel %s -o - 2>&1 | FileCheck %s
--- |
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-apple-ios"
define void @test_rem() {
entry:
ret void
}
...
---
name: test_rem
registers:
- { id: 0, class: _ }
- { id: 1, class: _ }
- { id: 2, class: _ }
- { id: 3, class: _ }
- { id: 4, class: _ }
- { id: 5, class: _ }
- { id: 6, class: _ }
- { id: 7, class: _ }
- { id: 8, class: _ }
body: |
bb.0.entry:
liveins: %x0, %x1, %x2, %x3
; CHECK: [[QUOT:%[0-9]+]](64) = G_UDIV s64 %0, %1
; CHECK: [[PROD:%[0-9]+]](64) = G_MUL s64 [[QUOT]], %1
; CHECK: [[RES:%[0-9]+]](64) = G_SUB s64 %0, [[PROD]]
%0(64) = COPY %x0
%1(64) = COPY %x1
%2(64) = G_UREM s64 %0, %1
; CHECK: [[QUOT:%[0-9]+]](32) = G_SDIV s32 %3, %4
; CHECK: [[PROD:%[0-9]+]](32) = G_MUL s32 [[QUOT]], %4
; CHECK: [[RES:%[0-9]+]](32) = G_SUB s32 %3, [[PROD]]
%3(32) = G_TRUNC { s32, s64 } %0
%4(32) = G_TRUNC { s32, s64 } %1
%5(32) = G_SREM s32 %3, %4
; CHECK: [[LHS32:%[0-9]+]](32) = G_SEXT { s32, s8 } %6
; CHECK: [[RHS32:%[0-9]+]](32) = G_SEXT { s32, s8 } %7
; CHECK: [[QUOT32:%[0-9]+]](32) = G_SDIV s32 [[LHS32]], [[RHS32]]
; CHECK: [[QUOT:%[0-9]+]](8) = G_TRUNC { s8, s32 } [[QUOT32]]
; CHECK: [[PROD:%[0-9]+]](8) = G_MUL s8 [[QUOT]], %7
; CHECK: [[RES:%[0-9]+]](8) = G_SUB s8 %6, [[PROD]]
%6(8) = G_TRUNC { s8, s64 } %0
%7(8) = G_TRUNC { s8, s64 } %1
%8(8) = G_SREM s8 %6, %7
...

View File

@ -13,6 +13,7 @@
using namespace llvm;
using llvm::MachineLegalizer::LegalizeAction::Legal;
using llvm::MachineLegalizer::LegalizeAction::Lower;
using llvm::MachineLegalizer::LegalizeAction::NarrowScalar;
using llvm::MachineLegalizer::LegalizeAction::WidenScalar;
using llvm::MachineLegalizer::LegalizeAction::FewerElements;
@ -26,6 +27,7 @@ namespace llvm {
std::ostream &
operator<<(std::ostream &OS, const llvm::MachineLegalizer::LegalizeAction Act) {
switch (Act) {
case Lower: OS << "Lower"; break;
case Legal: OS << "Legal"; break;
case NarrowScalar: OS << "NarrowScalar"; break;
case WidenScalar: OS << "WidenScalar"; break;