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:
parent
94b2dc6476
commit
a9938048f7
@ -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
|
||||
///
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
52
test/CodeGen/AArch64/GlobalISel/legalize-rem.mir
Normal file
52
test/CodeGen/AArch64/GlobalISel/legalize-rem.mir
Normal 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
|
||||
|
||||
...
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user