Subzero. Adds a pass for target-specific helper call generation.
This pass gives Targets the ability to pre-lower high-level
instructions that will later be lowered to a target-specific helper,
e.g., 64-bit division on targets that can't natively handle them.
This is a pre-requirement for correct outargs pre-allocation during
function prolog.
R=sehr@chromium.org
Review URL: https://codereview.chromium.org/1455033005 .
diff --git a/src/IceInst.h b/src/IceInst.h
index 7505924..a04584e 100644
--- a/src/IceInst.h
+++ b/src/IceInst.h
@@ -378,34 +378,40 @@
public:
static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
- Operand *CallTarget, bool HasTailCall) {
+ Operand *CallTarget, bool HasTailCall,
+ bool IsTargetHelperCall = false) {
/// Set HasSideEffects to true so that the call instruction can't be
/// dead-code eliminated. IntrinsicCalls can override this if the particular
/// intrinsic is deletable and has no side-effects.
constexpr bool HasSideEffects = true;
constexpr InstKind Kind = Inst::Call;
- return new (Func->allocate<InstCall>()) InstCall(
- Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind);
+ return new (Func->allocate<InstCall>())
+ InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
+ IsTargetHelperCall, HasSideEffects, Kind);
}
void addArg(Operand *Arg) { addSource(Arg); }
Operand *getCallTarget() const { return getSrc(0); }
Operand *getArg(SizeT I) const { return getSrc(I + 1); }
SizeT getNumArgs() const { return getSrcSize() - 1; }
bool isTailcall() const { return HasTailCall; }
+ bool isTargetHelperCall() const { return IsTargetHelperCall; }
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return Inst->getKind() == Call; }
Type getReturnType() const;
protected:
InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
- bool HasTailCall, bool HasSideEff, InstKind Kind)
- : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) {
+ bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
+ InstKind Kind)
+ : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
+ IsTargetHelperCall(IsTargetHelperCall) {
HasSideEffects = HasSideEff;
addSource(CallTarget);
}
private:
- bool HasTailCall;
+ const bool HasTailCall;
+ const bool IsTargetHelperCall;
};
/// Cast instruction (a.k.a. conversion operation).
@@ -570,8 +576,8 @@
private:
InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
- : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects,
- Inst::IntrinsicCall),
+ : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
+ Info.HasSideEffects, Inst::IntrinsicCall),
Info(Info) {}
const Intrinsics::IntrinsicInfo Info;
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 92223c9..a5bd86b 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -137,6 +137,16 @@
return nullptr;
}
+void TargetLowering::genTargetHelperCalls() {
+ for (CfgNode *Node : Func->getNodes()) {
+ Context.init(Node);
+ while (!Context.atEnd()) {
+ PostIncrLoweringContext _(Context);
+ genTargetHelperCallFor(Context.getCur());
+ }
+ }
+}
+
void TargetLowering::doAddressOpt() {
if (llvm::isa<InstLoad>(*Context.getCur()))
doAddressOptLoad();
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index c613d99..5489b8b 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -170,6 +170,8 @@
Func->setError("Target doesn't specify O2 lowering steps.");
}
+ /// Generates calls to intrinsics for operations the Target can't handle.
+ void genTargetHelperCalls();
/// Tries to do address mode optimization on a single instruction.
void doAddressOpt();
/// Randomly insert NOPs.
@@ -308,6 +310,8 @@
virtual void lowerUnreachable(const InstUnreachable *Inst) = 0;
virtual void lowerOther(const Inst *Instr);
+ virtual void genTargetHelperCallFor(Inst *Instr) = 0;
+
virtual void doAddressOptLoad() {}
virtual void doAddressOptStore() {}
virtual void doMockBoundsCheck(Operand *) {}
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 24cced8..60d3a37 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -238,6 +238,7 @@
// TODO(stichnot): share passes with X86?
// https://code.google.com/p/nativeclient/issues/detail?id=4094
+ genTargetHelperCalls();
// Do not merge Alloca instructions, and lay out the stack.
static constexpr bool SortAndCombineAllocas = false;
@@ -344,6 +345,7 @@
TimerMarker T(TimerStack::TT_Om1, Func);
// TODO: share passes with X86?
+ genTargetHelperCalls();
// Do not merge Alloca instructions, and lay out the stack.
static constexpr bool SortAndCombineAllocas = false;
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 318bce5..c0266eb 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -237,6 +237,7 @@
void lowerSwitch(const InstSwitch *Inst) override;
void lowerUnreachable(const InstUnreachable *Inst) override;
void prelowerPhis() override;
+ void genTargetHelperCallFor(Inst *Instr) override { (void)Instr; }
void doAddressOptLoad() override;
void doAddressOptStore() override;
void randomlyInsertNop(float Probability,
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 8e24808..85a9a46 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -91,6 +91,7 @@
// TODO(stichnot): share passes with X86?
// https://code.google.com/p/nativeclient/issues/detail?id=4094
+ genTargetHelperCalls();
// Merge Alloca instructions, and lay out the stack.
static constexpr bool SortAndCombineAllocas = true;
@@ -191,6 +192,7 @@
TimerMarker T(TimerStack::TT_Om1, Func);
// TODO: share passes with X86?
+ genTargetHelperCalls();
// Do not merge Alloca instructions, and lay out the stack.
static constexpr bool SortAndCombineAllocas = false;
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 1f91eee..5523360 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -235,6 +235,7 @@
void lowerSwitch(const InstSwitch *Inst) override;
void lowerUnreachable(const InstUnreachable *Inst) override;
void prelowerPhis() override;
+ void genTargetHelperCallFor(Inst *Instr) override { (void)Instr; }
void doAddressOptLoad() override;
void doAddressOptStore() override;
void randomlyInsertNop(float Probability,
diff --git a/src/IceTargetLoweringX86Base.h b/src/IceTargetLoweringX86Base.h
index 90bbed2..3127151 100644
--- a/src/IceTargetLoweringX86Base.h
+++ b/src/IceTargetLoweringX86Base.h
@@ -182,6 +182,7 @@
void lowerOther(const Inst *Instr) override;
void lowerRMW(const typename Traits::Insts::FakeRMW *RMW);
void prelowerPhis() override;
+ void genTargetHelperCallFor(Inst *Instr) override { (void)Instr; }
void doAddressOptLoad() override;
void doAddressOptStore() override;
void doMockBoundsCheck(Operand *Opnd) override;
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index 739ebb5..2653925 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -302,6 +302,8 @@
template <class Machine> void TargetX86Base<Machine>::translateO2() {
TimerMarker T(TimerStack::TT_O2, Func);
+ genTargetHelperCalls();
+
// Merge Alloca instructions, and lay out the stack.
static constexpr bool SortAndCombineAllocas = true;
Func->processAllocas(SortAndCombineAllocas);
@@ -425,6 +427,8 @@
template <class Machine> void TargetX86Base<Machine>::translateOm1() {
TimerMarker T(TimerStack::TT_Om1, Func);
+ genTargetHelperCalls();
+
// Do not merge Alloca instructions, and lay out the stack.
static constexpr bool SortAndCombineAllocas = false;
Func->processAllocas(SortAndCombineAllocas);