aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMISelDAGToDAG.cpp')
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp137
1 files changed, 119 insertions, 18 deletions
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 81229794a2..00214663c7 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -35,8 +35,17 @@
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetOptions.h"
+// @LOCALMOD-START
+#include "llvm/Support/CommandLine.h"
+namespace llvm {
+ extern cl::opt<bool> FlagSfiLoad;
+ extern cl::opt<bool> FlagSfiStore;
+}
+// @LOCALMOD-END
+
using namespace llvm;
+
static cl::opt<bool>
DisableShifterOp("disable-shifter-op", cl::Hidden,
cl::desc("Disable isel of shifter-op"),
@@ -109,21 +118,24 @@ public:
bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc);
- AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base,
+ AddrMode2Type SelectAddrMode2Worker(SDNode *Op, SDValue N, SDValue &Base,
SDValue &Offset, SDValue &Opc);
- bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset,
+ bool SelectAddrMode2Base(SDNode *Op,
+ SDValue N, SDValue &Base, SDValue &Offset,
SDValue &Opc) {
- return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE;
+ return SelectAddrMode2Worker(Op, N, Base, Offset, Opc) == AM2_BASE;
}
- bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset,
+ bool SelectAddrMode2ShOp(SDNode *Op,
+ SDValue N, SDValue &Base, SDValue &Offset,
SDValue &Opc) {
- return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP;
+ return SelectAddrMode2Worker(Op, N, Base, Offset, Opc) == AM2_SHOP;
}
- bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset,
+ bool SelectAddrMode2(SDNode *Op,
+ SDValue N, SDValue &Base, SDValue &Offset,
SDValue &Opc) {
- SelectAddrMode2Worker(N, Base, Offset, Opc);
+ SelectAddrMode2Worker(Op, N, Base, Offset, Opc);
// return SelectAddrMode2ShOp(N, Base, Offset, Opc);
// This always matches one way or another.
return true;
@@ -136,7 +148,7 @@ public:
bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc);
bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
- bool SelectAddrMode3(SDValue N, SDValue &Base,
+ bool SelectAddrMode3(SDNode *Op, SDValue N, SDValue &Base,
SDValue &Offset, SDValue &Opc);
bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
SDValue &Offset, SDValue &Opc);
@@ -435,6 +447,22 @@ bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
return true;
}
+// @LOCALMOD-START
+static bool ShouldOperandBeUnwrappedForUseAsBaseAddress(
+ SDValue& N, const ARMSubtarget* Subtarget) {
+ assert (N.getOpcode() == ARMISD::Wrapper);
+ // Never use this transformation if constant island pools are disallowed
+ if (FlagSfiDisableCP) return false;
+
+ // always apply this when we do not have movt/movw available
+ // (if we do have movt/movw we be able to get rid of the
+ // constant pool entry altogether)
+ if (!Subtarget->useMovt()) return true;
+ // explain why we do not want to use this for TargetGlobalAddress
+ if (N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) return true;
+ return false;
+}
+// @LOCALMOD-END
bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
SDValue &Base,
@@ -453,8 +481,8 @@ bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
}
if (N.getOpcode() == ARMISD::Wrapper &&
- !(Subtarget->useMovt() &&
- N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
+ // @LOCALMOD
+ ShouldOperandBeUnwrappedForUseAsBaseAddress(N, Subtarget)) {
Base = N.getOperand(0);
} else
Base = N;
@@ -488,6 +516,11 @@ bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
SDValue &Opc) {
+ // @LOCALMOD-BEGIN
+ // Disallow offsets of Reg + Reg (which may escape sandbox).
+ if (Subtarget->isTargetNaCl())
+ return false;
+ // @LOCALMOD-END
if (N.getOpcode() == ISD::MUL &&
((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) {
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
@@ -583,10 +616,24 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset,
//-----
-AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
+AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDNode *Op,
+ SDValue N,
SDValue &Base,
SDValue &Offset,
+// @LOCALMOD-START
+// Note: In the code below we do not want "Offset" to be real register to
+// not violate ARM sandboxing.
+// @LOCALMOD-END
SDValue &Opc) {
+ // @LOCALMOD-START
+ // Avoid two reg addressing mode for loads and stores
+ const bool restrict_addressing_modes_for_nacl =
+ (FlagSfiLoad && (Op->getOpcode() == ISD::LOAD)) ||
+ (FlagSfiStore && (Op->getOpcode() == ISD::STORE));
+ // This is neither a sandboxable load nor a sandboxable store.
+ if (!restrict_addressing_modes_for_nacl) {
+ // @LOCALMOD-END
+
if (N.getOpcode() == ISD::MUL &&
(!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) {
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
@@ -610,6 +657,7 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
}
}
}
+ } // @LOCALMOD
if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
// ISD::OR that is equivalent to an ADD.
@@ -619,8 +667,8 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
int FI = cast<FrameIndexSDNode>(N)->getIndex();
Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
} else if (N.getOpcode() == ARMISD::Wrapper &&
- !(Subtarget->useMovt() &&
- N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
+ // @LOCALMOD
+ ShouldOperandBeUnwrappedForUseAsBaseAddress(N, Subtarget)) {
Base = N.getOperand(0);
}
Offset = CurDAG->getRegister(0, MVT::i32);
@@ -653,7 +701,7 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
return AM2_BASE;
}
}
-
+
if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) {
// Compute R +/- (R << N) and reuse it.
Base = N;
@@ -663,6 +711,24 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N,
MVT::i32);
return AM2_BASE;
}
+
+ // @LOCALMOD-START
+ // Keep load and store addressing modes simple
+ if (restrict_addressing_modes_for_nacl) {
+ Base = N;
+ if (N.getOpcode() == ISD::FrameIndex) {
+ int FI = cast<FrameIndexSDNode>(N)->getIndex();
+ Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
+ } else if (N.getOpcode() == ARMISD::Wrapper) {
+ Base = N.getOperand(0);
+ }
+ Offset = CurDAG->getRegister(0, MVT::i32);
+ Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0,
+ ARM_AM::no_shift),
+ MVT::i32);
+ return AM2_BASE;
+ }
+ // @LOCALMOD-END
// Otherwise this is R +/- [possibly shifted] R.
ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub;
@@ -731,13 +797,27 @@ bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N,
if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val))
return false;
+ // @LOCALMOD-BEGIN
+ // Avoid two reg addressing mode for loads and stores
+ const bool restrict_addressing_modes_for_nacl =
+ (FlagSfiLoad && (Op->getOpcode() == ISD::LOAD)) ||
+ (FlagSfiStore && (Op->getOpcode() == ISD::STORE));
+ // @LOCALMOD-END
+
+
Offset = N;
ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
unsigned ShAmt = 0;
if (ShOpcVal != ARM_AM::no_shift) {
// Check to see if the RHS of the shift is a constant, if not, we can't fold
// it.
- if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+
+ //if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+ ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1));
+ // @LOCALMOD-BEGIN
+ // Neither a sandboxable load nor a sandboxable store.
+ if (!restrict_addressing_modes_for_nacl && Sh ) {
+ // @LOCALMOD-END
ShAmt = Sh->getZExtValue();
if (isShifterOpProfitable(N, ShOpcVal, ShAmt))
Offset = N.getOperand(0);
@@ -800,16 +880,25 @@ bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
return true;
}
-bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
+bool ARMDAGToDAGISel::SelectAddrMode3(SDNode *Op, SDValue N,
SDValue &Base, SDValue &Offset,
SDValue &Opc) {
+ // @LOCALMOD-START
+ // Avoid two reg addressing mode for loads and stores
+ const bool restrict_addressing_modes_for_nacl =
+ (FlagSfiLoad && (Op->getOpcode() == ISD::LOAD)) ||
+ (FlagSfiStore && (Op->getOpcode() == ISD::STORE));
+ if (!restrict_addressing_modes_for_nacl) {
+ // @LOCALMOD-END
if (N.getOpcode() == ISD::SUB) {
+
// X - C is canonicalize to X + -C, no need to handle it here.
Base = N.getOperand(0);
Offset = N.getOperand(1);
Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32);
return true;
}
+ } // @LOCALMOD-END
if (!CurDAG->isBaseWithConstantOffset(N)) {
Base = N;
@@ -842,6 +931,16 @@ bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
return true;
}
+ // @LOCALMOD-START
+ // A sandboxable load or a sandboxable store.
+ if (restrict_addressing_modes_for_nacl) {
+ Base = N;
+ Offset = CurDAG->getRegister(0, MVT::i32);
+ Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32);
+ return true;
+ }
+ // @LOCALMOD-END
+
Base = N.getOperand(0);
Offset = N.getOperand(1);
Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32);
@@ -876,8 +975,8 @@ bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N,
int FI = cast<FrameIndexSDNode>(N)->getIndex();
Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
} else if (N.getOpcode() == ARMISD::Wrapper &&
- !(Subtarget->useMovt() &&
- N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
+ // @LOCALMOD
+ ShouldOperandBeUnwrappedForUseAsBaseAddress(N, Subtarget)) {
Base = N.getOperand(0);
}
Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0),
@@ -2473,6 +2572,8 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
!ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
}
+ if (FlagSfiDisableCP) UseCP = false; // @LOCALMOD
+
if (UseCP) {
SDValue CPIdx =
CurDAG->getTargetConstantPool(ConstantInt::get(