diff options
Diffstat (limited to 'lib/Target/ARM/ARMISelDAGToDAG.cpp')
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 137 |
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( |