Add a basic enum for ARM InstructionSet / cpu features.
That way, we don't have to use -mattr=sse2 for ARM in
cross tests, etc.
Default to NEON for now. Also put in an entry for HW
divide in ARM mode. There's bunches of features that are
possible though, e.g.,:
https://github.com/llvm-mirror/llvm/blob/master/lib/Target/ARM/ARM.td
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1191573003.
diff --git a/src/IceClFlags.cpp b/src/IceClFlags.cpp
index a433b9a..5cd4a6b 100644
--- a/src/IceClFlags.cpp
+++ b/src/IceClFlags.cpp
@@ -142,11 +142,17 @@
clEnumValEnd));
cl::opt<Ice::TargetInstructionSet> TargetInstructionSet(
"mattr", cl::desc("Target architecture attributes"),
- cl::init(Ice::X86InstructionSet_SSE2),
- cl::values(clEnumValN(Ice::X86InstructionSet_SSE2, "sse2",
- "Enable SSE2 instructions (default)"),
+ cl::init(Ice::BaseInstructionSet),
+ cl::values(clEnumValN(Ice::BaseInstructionSet, "base",
+ "Target chooses baseline instruction set (default)"),
+ clEnumValN(Ice::X86InstructionSet_SSE2, "sse2",
+ "Enable X86 SSE2 instructions"),
clEnumValN(Ice::X86InstructionSet_SSE4_1, "sse4.1",
- "Enable SSE 4.1 instructions"),
+ "Enable X86 SSE 4.1 instructions"),
+ clEnumValN(Ice::ARM32InstructionSet_Neon, "neon",
+ "Enable ARM Neon instructions"),
+ clEnumValN(Ice::ARM32InstructionSet_HWDivArm, "hwdiv-arm",
+ "Enable ARM integer divide instructions in ARM mode"),
clEnumValEnd));
cl::opt<std::string>
TestPrefix("prefix",
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index a4aa517..2d3c5c1 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -135,8 +135,21 @@
} // end of anonymous namespace
TargetARM32::TargetARM32(Cfg *Func)
- : TargetLowering(Func), UsesFramePointer(false), NeedsStackAlignment(false),
- MaybeLeafFunc(true), SpillAreaSizeBytes(0) {
+ : TargetLowering(Func), InstructionSet(ARM32InstructionSet::Begin),
+ UsesFramePointer(false), NeedsStackAlignment(false), MaybeLeafFunc(true),
+ SpillAreaSizeBytes(0) {
+ static_assert(
+ (ARM32InstructionSet::End - ARM32InstructionSet::Begin) ==
+ (TargetInstructionSet::ARM32InstructionSet_End -
+ TargetInstructionSet::ARM32InstructionSet_Begin),
+ "ARM32InstructionSet range different from TargetInstructionSet");
+ if (Func->getContext()->getFlags().getTargetInstructionSet() !=
+ TargetInstructionSet::BaseInstructionSet) {
+ InstructionSet = static_cast<ARM32InstructionSet>(
+ (Func->getContext()->getFlags().getTargetInstructionSet() -
+ TargetInstructionSet::ARM32InstructionSet_Begin) +
+ ARM32InstructionSet::Begin);
+ }
// TODO: Don't initialize IntegerRegisters and friends every time.
// Instead, initialize in some sort of static initializer for the
// class.
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 7f5fdc8..98dd20e 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -75,6 +75,16 @@
void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
size_t BasicFrameOffset, size_t &InArgsSizeBytes);
+ enum ARM32InstructionSet {
+ Begin,
+ // Neon is the PNaCl baseline instruction set.
+ Neon = Begin,
+ HWDivArm, // HW divide in ARM mode (not just Thumb mode).
+ End
+ };
+
+ ARM32InstructionSet getInstructionSet() const { return InstructionSet; }
+
protected:
explicit TargetARM32(Cfg *Func);
@@ -288,6 +298,7 @@
Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred));
}
+ ARM32InstructionSet InstructionSet;
bool UsesFramePointer;
bool NeedsStackAlignment;
bool MaybeLeafFunc;
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index dbb4e4a..b686579 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -395,16 +395,20 @@
}
TargetX8632::TargetX8632(Cfg *Func)
- : TargetLowering(Func),
- InstructionSet(static_cast<X86InstructionSet>(
- Func->getContext()->getFlags().getTargetInstructionSet() -
- TargetInstructionSet::X86InstructionSet_Begin)),
+ : TargetLowering(Func), InstructionSet(X86InstructionSet::Begin),
IsEbpBasedFrame(false), NeedsStackAlignment(false),
SpillAreaSizeBytes(0) {
static_assert((X86InstructionSet::End - X86InstructionSet::Begin) ==
(TargetInstructionSet::X86InstructionSet_End -
TargetInstructionSet::X86InstructionSet_Begin),
"X86InstructionSet range different from TargetInstructionSet");
+ if (Func->getContext()->getFlags().getTargetInstructionSet() !=
+ TargetInstructionSet::BaseInstructionSet) {
+ InstructionSet = static_cast<X86InstructionSet>(
+ (Func->getContext()->getFlags().getTargetInstructionSet() -
+ TargetInstructionSet::X86InstructionSet_Begin) +
+ X86InstructionSet::Begin);
+ }
// TODO: Don't initialize IntegerRegisters and friends every time.
// Instead, initialize in some sort of static initializer for the
// class.
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index a921294..0b46e1b 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -562,7 +562,7 @@
bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
- const X86InstructionSet InstructionSet;
+ X86InstructionSet InstructionSet;
bool IsEbpBasedFrame;
bool NeedsStackAlignment;
size_t SpillAreaSizeBytes;
diff --git a/src/IceTypes.h b/src/IceTypes.h
index 297fad3..9353d74 100644
--- a/src/IceTypes.h
+++ b/src/IceTypes.h
@@ -43,11 +43,16 @@
// The list of all target instruction sets. Individual targets will
// map this to include only what is valid for the target.
enum TargetInstructionSet {
+ // Represents baseline that can be assumed for a target (usually "Begin").
+ BaseInstructionSet,
X86InstructionSet_Begin,
- // SSE2 is the PNaCl baseline instruction set.
X86InstructionSet_SSE2 = X86InstructionSet_Begin,
X86InstructionSet_SSE4_1,
X86InstructionSet_End,
+ ARM32InstructionSet_Begin,
+ ARM32InstructionSet_Neon = ARM32InstructionSet_Begin,
+ ARM32InstructionSet_HWDivArm,
+ ARM32InstructionSet_End,
};
enum OptLevel { Opt_m1, Opt_0, Opt_1, Opt_2 };