Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Unified Diff: src/IceInstARM32.h

Issue 1214693004: ARM lowering integer divide and remainder, with div by 0 checks. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: rebase, refactor, and fix switch MINIMAL=1 Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceGlobalContext.cpp ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceInstARM32.h
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
index 8167ed45c60fdf3b3a9623c49dd0bcac00ed73a7..8b69be9757caa2cb7d7ba8899043d893a3e69547 100644
--- a/src/IceInstARM32.h
+++ b/src/IceInstARM32.h
@@ -262,10 +262,12 @@ public:
Call,
Cmp,
Eor,
+ Label,
jvoung (off chromium) 2015/06/29 21:44:28 Would it make sense to just make Label part of the
Jim Stichnoth 2015/06/30 14:14:08 That seems reasonable.
jvoung (off chromium) 2015/06/30 16:58:07 Okay will try that in a separate CL.
Ldr,
Lsl,
Lsr,
Mla,
+ Mls,
Mov,
Movt,
Movw,
@@ -277,9 +279,13 @@ public:
Ret,
Rsb,
Sbc,
+ Sdiv,
Str,
Sub,
Sxt,
+ Trap,
+ Tst,
+ Udiv,
Umull,
Uxt
};
@@ -322,6 +328,8 @@ public:
const Cfg *Func);
static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst,
const Cfg *Func, bool SetFlags);
+ static void emitFourAddr(const char *Opcode, const InstARM32Pred *Inst,
+ const Cfg *Func);
protected:
CondARM32::Cond Predicate;
@@ -516,6 +524,55 @@ private:
bool SetFlags;
};
+// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
+template <InstARM32::InstKindARM32 K>
+class InstARM32FourAddrGPR : public InstARM32Pred {
+ InstARM32FourAddrGPR() = delete;
+ InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
+ InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
+
+public:
+ // Every operand must be a register.
+ static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src1,
+ Variable *Src2, Variable *Src3,
+ CondARM32::Cond Predicate) {
+ return new (Func->allocate<InstARM32FourAddrGPR>())
+ InstARM32FourAddrGPR(Func, Dest, Src1, Src2, Src3, Predicate);
+ }
+ void emit(const Cfg *Func) const override {
+ if (!BuildDefs::dump())
+ return;
+ emitFourAddr(Opcode, this, Func);
+ }
+ void emitIAS(const Cfg *Func) const override {
+ (void)Func;
+ llvm::report_fatal_error("Not yet implemented");
+ }
+ void dump(const Cfg *Func) const override {
+ if (!BuildDefs::dump())
+ return;
+ Ostream &Str = Func->getContext()->getStrDump();
+ dumpDest(Func);
+ Str << " = ";
+ dumpOpcodePred(Str, Opcode, getDest()->getType());
+ Str << " ";
+ dumpSources(Func);
+ }
+ static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
+
+private:
+ InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1,
+ Variable *Src2, Variable *Src3,
+ CondARM32::Cond Predicate)
+ : InstARM32Pred(Func, K, 3, Dest, Predicate) {
+ addSource(Src1);
+ addSource(Src2);
+ addSource(Src3);
+ }
+
+ static const char *Opcode;
+};
+
typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc;
typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add;
typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And;
@@ -528,7 +585,9 @@ typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul;
typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr;
typedef InstARM32ThreeAddrGPR<InstARM32::Rsb> InstARM32Rsb;
typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc;
+typedef InstARM32ThreeAddrGPR<InstARM32::Sdiv> InstARM32Sdiv;
typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub;
+typedef InstARM32ThreeAddrGPR<InstARM32::Udiv> InstARM32Udiv;
// Move instruction (variable <- flex). This is more of a pseudo-inst.
// If var is a register, then we use "mov". If var is stack, then we use
// "str" to store to the stack.
@@ -543,6 +602,33 @@ typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn;
// but we aren't using that for now, so just model as a Unaryop.
typedef InstARM32UnaryopGPR<InstARM32::Sxt> InstARM32Sxt;
typedef InstARM32UnaryopGPR<InstARM32::Uxt> InstARM32Uxt;
+typedef InstARM32FourAddrGPR<InstARM32::Mla> InstARM32Mla;
+typedef InstARM32FourAddrGPR<InstARM32::Mls> InstARM32Mls;
+
+// InstARM32Label represents an intra-block label that is the target
+// of an intra-block branch. The offset between the label and the
+// branch must be fit in the instruction immediate (considered "near").
+class InstARM32Label : public InstARM32 {
+ InstARM32Label() = delete;
+ InstARM32Label(const InstARM32Label &) = delete;
+ InstARM32Label &operator=(const InstARM32Label &) = delete;
+
+public:
+ static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
+ return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
+ }
+ uint32_t getEmitInstCount() const override { return 0; }
+ IceString getName(const Cfg *Func) const;
+ SizeT getNumber() const { return Number; }
+ void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
+ void dump(const Cfg *Func) const override;
+
+private:
+ InstARM32Label(Cfg *Func, TargetARM32 *Target);
+
+ SizeT Number; // used for unique label generation.
+};
// Direct branch instruction.
class InstARM32Br : public InstARM32Pred {
@@ -555,14 +641,16 @@ public:
static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
CfgNode *TargetFalse, CondARM32::Cond Predicate) {
assert(Predicate != CondARM32::AL);
+ const InstARM32Label *NoLabel = nullptr;
return new (Func->allocate<InstARM32Br>())
- InstARM32Br(Func, TargetTrue, TargetFalse, Predicate);
+ InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
}
// Create an unconditional branch to a node.
static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
const CfgNode *NoCondTarget = nullptr;
+ const InstARM32Label *NoLabel = nullptr;
return new (Func->allocate<InstARM32Br>())
- InstARM32Br(Func, NoCondTarget, Target, CondARM32::AL);
+ InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
}
// Create a non-terminator conditional branch to a node, with a
// fallthrough to the next instruction in the current node. This is
@@ -571,14 +659,26 @@ public:
CondARM32::Cond Predicate) {
assert(Predicate != CondARM32::AL);
const CfgNode *NoUncondTarget = nullptr;
+ const InstARM32Label *NoLabel = nullptr;
+ return new (Func->allocate<InstARM32Br>())
+ InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
+ }
+ // Create a conditional intra-block branch (or unconditional, if
+ // Condition==AL) to a label in the current block.
+ static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
+ CondARM32::Cond Predicate) {
+ const CfgNode *NoCondTarget = nullptr;
+ const CfgNode *NoUncondTarget = nullptr;
return new (Func->allocate<InstARM32Br>())
- InstARM32Br(Func, Target, NoUncondTarget, Predicate);
+ InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
}
const CfgNode *getTargetTrue() const { return TargetTrue; }
const CfgNode *getTargetFalse() const { return TargetFalse; }
bool optimizeBranch(const CfgNode *NextNode);
uint32_t getEmitInstCount() const override {
uint32_t Sum = 0;
+ if (Label)
+ ++Sum;
if (getTargetTrue())
++Sum;
if (getTargetFalse())
@@ -596,10 +696,11 @@ public:
private:
InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
- CondARM32::Cond Predicate);
+ const InstARM32Label *Label, CondARM32::Cond Predicate);
const CfgNode *TargetTrue;
const CfgNode *TargetFalse;
+ const InstARM32Label *Label; // Intra-block branch target
};
// AdjustStack instruction - subtracts SP by the given amount and
@@ -698,30 +799,6 @@ private:
CondARM32::Cond Predicate);
};
-// Multiply Accumulate: d := x * y + a
-class InstARM32Mla : public InstARM32Pred {
- InstARM32Mla() = delete;
- InstARM32Mla(const InstARM32Mla &) = delete;
- InstARM32Mla &operator=(const InstARM32Mla &) = delete;
-
-public:
- // Everything must be a register.
- static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0,
- Variable *Src1, Variable *Acc,
- CondARM32::Cond Predicate) {
- return new (Func->allocate<InstARM32Mla>())
- InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate);
- }
- void emit(const Cfg *Func) const override;
- void emitIAS(const Cfg *Func) const override;
- void dump(const Cfg *Func) const override;
- static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); }
-
-private:
- InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1,
- Variable *Acc, CondARM32::Cond Predicate);
-};
-
// Pop into a list of GPRs. Technically this can be predicated, but we don't
// need that functionality.
class InstARM32Pop : public InstARM32 {
@@ -816,6 +893,45 @@ private:
CondARM32::Cond Predicate);
};
+class InstARM32Trap : public InstARM32 {
+ InstARM32Trap() = delete;
+ InstARM32Trap(const InstARM32Trap &) = delete;
+ InstARM32Trap &operator=(const InstARM32Trap &) = delete;
+
+public:
+ static InstARM32Trap *create(Cfg *Func) {
+ return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
+ }
+ void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
+ void dump(const Cfg *Func) const override;
+ static bool classof(const Inst *Inst) { return isClassof(Inst, Trap); }
+
+private:
+ explicit InstARM32Trap(Cfg *Func);
+};
+
+class InstARM32Tst : public InstARM32Pred {
+ InstARM32Tst() = delete;
+ InstARM32Tst(const InstARM32Tst &) = delete;
+ InstARM32Tst &operator=(const InstARM32Tst &) = delete;
+
+public:
+ static InstARM32Tst *create(Cfg *Func, Variable *Src0, Operand *Src1,
+ CondARM32::Cond Predicate) {
+ return new (Func->allocate<InstARM32Tst>())
+ InstARM32Tst(Func, Src0, Src1, Predicate);
+ }
+ void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
+ void dump(const Cfg *Func) const override;
+ static bool classof(const Inst *Inst) { return isClassof(Inst, Tst); }
+
+private:
+ InstARM32Tst(Cfg *Func, Variable *Src0, Operand *Src1,
+ CondARM32::Cond Predicate);
+};
+
// Unsigned Multiply Long: d.lo, d.hi := x * y
class InstARM32Umull : public InstARM32Pred {
InstARM32Umull() = delete;
« no previous file with comments | « src/IceGlobalContext.cpp ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698