summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMLegalizerInfo.cpp52
-rw-r--r--llvm/lib/Target/ARM/ARMLegalizerInfo.h3
2 files changed, 55 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
index d1c5d964d95..9b86030fdd2 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -13,6 +13,8 @@
#include "ARMLegalizerInfo.h"
#include "ARMSubtarget.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
@@ -48,6 +50,11 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
setAction({Op, Ty}, Legal);
for (unsigned Op : {G_SDIV, G_UDIV}) {
+ for (auto Ty : {s8, s16})
+ // FIXME: We need WidenScalar here, but in the case of targets with
+ // software division we'll also need Libcall afterwards. Treat as Custom
+ // until we have better support for chaining legalization actions.
+ setAction({Op, Ty}, Custom);
if (ST.hasDivideInARMMode())
setAction({Op, s32}, Legal);
else
@@ -82,3 +89,48 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
computeTables();
}
+
+bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ MachineIRBuilder &MIRBuilder) const {
+ using namespace TargetOpcode;
+
+ switch (MI.getOpcode()) {
+ default:
+ return false;
+ case G_SDIV:
+ case G_UDIV: {
+ LLT Ty = MRI.getType(MI.getOperand(0).getReg());
+ if (Ty != LLT::scalar(16) && Ty != LLT::scalar(8))
+ return false;
+
+ // We need to widen to 32 bits and then maybe, if the target requires,
+ // transform into a libcall.
+ LegalizerHelper Helper(MIRBuilder.getMF());
+
+ MachineInstr *NewMI = nullptr;
+ Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
+ // Store the new, 32-bit div instruction.
+ if (MI->getOpcode() == G_SDIV || MI->getOpcode() == G_UDIV)
+ NewMI = MI;
+ });
+
+ auto Result = Helper.widenScalar(MI, 0, LLT::scalar(32));
+ Helper.MIRBuilder.stopRecordingInsertions();
+ if (Result == LegalizerHelper::UnableToLegalize) {
+ return false;
+ }
+ assert(NewMI && "Couldn't find widened instruction");
+ assert((NewMI->getOpcode() == G_SDIV || NewMI->getOpcode() == G_UDIV) &&
+ "Unexpected widened instruction");
+ assert(MRI.getType(NewMI->getOperand(0).getReg()).getSizeInBits() == 32 &&
+ "Unexpected type for the widened instruction");
+
+ Result = Helper.legalizeInstrStep(*NewMI);
+ if (Result == LegalizerHelper::UnableToLegalize) {
+ return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.h b/llvm/lib/Target/ARM/ARMLegalizerInfo.h
index 0b8a608a6bd..a9bdd367737 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.h
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.h
@@ -24,6 +24,9 @@ class ARMSubtarget;
class ARMLegalizerInfo : public LegalizerInfo {
public:
ARMLegalizerInfo(const ARMSubtarget &ST);
+
+ bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
+ MachineIRBuilder &MIRBuilder) const override;
};
} // End llvm namespace.
#endif
OpenPOWER on IntegriCloud