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

Unified Diff: lib/Target/X86/X86FastISel.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 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 | « lib/Target/X86/X86CallingConv.td ('k') | lib/Target/X86/X86FrameLowering.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Target/X86/X86FastISel.cpp
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index d43d1bce17704253d904eb25fb6294f666389ef3..c2fb20a17129953a47c1f2b77d64505b7ae4229a 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -39,8 +39,14 @@
#include "llvm/IR/Operator.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/ADT/Statistic.h" // @LOCALMOD
using namespace llvm;
+// @LOCALMOD-BEGIN
+#define DEBUG_TYPE "isel"
+STATISTIC(NumFastIselNaClFailures, "Number of instructions fast isel failed on for NaCl illegality");
+// @LOCALMOD-END
+
namespace {
class X86FastISel final : public FastISel {
@@ -501,6 +507,85 @@ bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT,
return true;
}
+/// @LOCALMOD-BEGIN
+/// isLegalAddressingModeForNaCl - Determine if the addressing mode is
+/// legal for NaCl translation. If not, the caller is expected to
+/// reject the instruction for fast-ISel code generation.
+///
+/// The logic for the test is translated from the corresponding logic
+/// in X86DAGToDAGISel::LegalizeAddressingModeForNaCl(). It can't be
+/// used directly due to the X86AddressMode vs X86ISelAddressMode
+/// types. As such, any changes to isLegalAddressingModeForNaCl() and
+/// X86DAGToDAGISel::LegalizeAddressingModeForNaCl() need to be
+/// synchronized. The original conditions are indicated in comments.
+static bool isLegalAddressingModeForNaCl(const X86Subtarget *Subtarget,
+ const X86AddressMode &AM) {
+ if (Subtarget->isTargetNaCl64()) {
+ // Return true (i.e., is legal) if the equivalent of
+ // X86ISelAddressMode::isRIPRelative() is true.
+ if (AM.BaseType == X86AddressMode::RegBase &&
+ AM.Base.Reg == X86::RIP)
+ return true;
+
+ // Check for the equivalent of
+ // (!AM.hasBaseOrIndexReg() &&
+ // !AM.hasSymbolicDisplacement() &&
+ // AM.Disp < 0)
+ if (!((AM.BaseType == X86AddressMode::RegBase && AM.Base.Reg) ||
+ AM.IndexReg) &&
+ !AM.GV &&
+ AM.Disp < 0) {
+ ++NumFastIselNaClFailures;
+ return false;
+ }
+
+ // At this point in the LegalizeAddressingModeForNaCl() code, it
+ // normalizes an addressing mode with a base register and no index
+ // register into an equivalent mode with an index register and no
+ // base register. Since we don't modify AM, we may have to check
+ // both the base and index register fields in the remainder of the
+ // tests.
+
+ // Check for the equivalent of
+ // ((AM.BaseType == X86ISelAddressMode::FrameIndexBase || AM.GV || AM.CP) &&
+ // AM.IndexReg.getNode() &&
+ // AM.Disp > 0)
+ // Note: X86AddressMode doesn't have a CP analogue
+ if ((AM.BaseType == X86AddressMode::FrameIndexBase || AM.GV) &&
+ ((AM.BaseType == X86AddressMode::RegBase && AM.Base.Reg) ||
+ AM.IndexReg) &&
+ AM.Disp > 0) {
+ ++NumFastIselNaClFailures;
+ return false;
+ }
+
+ // Check for the equivalent of
+ // ((AM.BaseType == X86ISelAddressMode::RegBase) &&
+ // AM.Base_Reg.getNode() &&
+ // AM.IndexReg.getNode())
+ if ((AM.BaseType == X86AddressMode::RegBase) &&
+ AM.Base.Reg &&
+ AM.IndexReg) {
+ ++NumFastIselNaClFailures;
+ return false;
+ }
+
+ // See X86DAGToDAGISel::FoldOffsetIntoAddress().
+ // Check for the equivalent of
+ // ((AM.BaseType == X86ISelAddressMode::RegBase ||
+ // AM.BaseType == X86ISelAddressMode::FrameIndexBase) &&
+ // (Val > 65535 || Val < -65536))
+ if ((AM.BaseType == X86AddressMode::RegBase ||
+ AM.BaseType == X86AddressMode::FrameIndexBase) &&
+ (AM.Disp > 65535 || AM.Disp < -65536)) {
+ ++NumFastIselNaClFailures;
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
// Handle constant address.
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
@@ -566,6 +651,14 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
if (Subtarget->isPICStyleRIPRel())
StubAM.Base.Reg = X86::RIP;
+ // @LOCALMOD-BEGIN
+ } else if (Subtarget->isTargetNaCl64()) {
+ Opc = X86::MOV32rm;
+ RC = &X86::GR32RegClass;
+
+ if (Subtarget->isPICStyleRIPRel())
+ StubAM.Base.Reg = X86::RIP;
+ // @LOCALMOD-END
} else {
Opc = X86::MOV32rm;
RC = &X86::GR32RegClass;
@@ -593,6 +686,21 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
// If all else fails, try to materialize the value in a register.
if (!AM.GV || !Subtarget->isPICStyleRIPRel()) {
+ // @LOCALMOD-START
+ if (Subtarget->isTargetNaCl64()) {
+ // We are about use a register in an addressing mode. However, x86-64
+ // NaCl does not allow arbitrary r+r addressing. One of the regs must
+ // be %r15 (inserted by the NaClRewritePass). Check that we will only
+ // end up with one reg defined after this.
+ if ((AM.Base.Reg == 0) && (AM.IndexReg == 0)) {
+ // Put into index register so that the NaCl rewrite pass will
+ // convert this to a 64-bit address.
+ AM.IndexReg = getRegForValue(V);
+ return AM.IndexReg != 0;
+ }
+ return false;
+ }
+ // @LOCALMOD-END
if (AM.Base.Reg == 0) {
AM.Base.Reg = getRegForValue(V);
return AM.Base.Reg != 0;
@@ -609,6 +717,16 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
/// X86SelectAddress - Attempt to fill in an address from the given value.
///
+/// @LOCALMOD-BEGIN
+/// All "return v;" statements must be converted to
+/// "return (v) && isLegalAddressingModeForNaCl(Subtarget, AM);"
+/// except that "return false;" can of course be left unchanged.
+///
+/// Since X86SelectAddress() recursively builds up the AM result
+/// object, there is a risk that an intermediate result could be
+/// rejected in a situation where the final result was in fact legal,
+/// though it is hard to imagine this happening.
+/// @LOCALMOD-END
bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
SmallVector<const Value *, 32> GEPs;
redo_gep:
@@ -660,7 +778,7 @@ redo_gep:
if (SI != FuncInfo.StaticAllocaMap.end()) {
AM.BaseType = X86AddressMode::FrameIndexBase;
AM.Base.FrameIndex = SI->second;
- return true;
+ return isLegalAddressingModeForNaCl(Subtarget, AM); // @LOCALMOD
}
break;
}
@@ -746,7 +864,7 @@ redo_gep:
V = GEP;
goto redo_gep;
} else if (X86SelectAddress(U->getOperand(0), AM)) {
- return true;
+ return isLegalAddressingModeForNaCl(Subtarget, AM); // @LOCALMOD
}
// If we couldn't merge the gep value into this addr mode, revert back to
@@ -756,7 +874,7 @@ redo_gep:
for (SmallVectorImpl<const Value *>::reverse_iterator
I = GEPs.rbegin(), E = GEPs.rend(); I != E; ++I)
if (handleConstantAddresses(*I, AM))
- return true;
+ return isLegalAddressingModeForNaCl(Subtarget, AM); // @LOCALMOD
return false;
unsupported_gep:
@@ -765,7 +883,11 @@ redo_gep:
}
}
- return handleConstantAddresses(V, AM);
+ // @LOCALMOD-START
+ if (handleConstantAddresses(V, AM))
+ return isLegalAddressingModeForNaCl(Subtarget, AM);
+ return false;
+ // @LOCALMOD-END
}
/// X86SelectCallAddress - Attempt to fill in an address from the given value.
@@ -1029,10 +1151,15 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
unsigned Reg = X86MFInfo->getSRetReturnReg();
assert(Reg &&
"SRetReturnReg should have been set in LowerFormalArguments()!");
- unsigned RetReg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
+ // @LOCALMOD-BEGIN -- Ensure that the register classes match.
+ // At this point, SRetReturnReg is EDI, because PointerTy() for NaCl
+ // is i32. We then copy to EAX instead of RAX. Alternatively, we could
+ // have zero-extended EDI to RDI then copy to RAX, but this has a smaller
+ // encoding (2 bytes vs 3 bytes).
+ unsigned CopyTo = Subtarget->isTarget64BitLP64() ? X86::RAX : X86::EAX;
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY),
- RetReg).addReg(Reg);
- RetRegs.push_back(RetReg);
+ CopyTo).addReg(Reg);
+ // @LOCALMOD-END
}
// Now emit the RET.
@@ -2107,6 +2234,7 @@ bool X86FastISel::TryEmitSmallMemcpy(X86AddressMode DestAM,
else if (Len >= 2)
VT = MVT::i16;
else {
+ assert(Len == 1);
VT = MVT::i8;
}
@@ -2144,14 +2272,14 @@ bool X86FastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
case MVT::i64: Opc = X86::MOV64rm; RC = &X86::GR64RegClass; break;
}
- // This needs to be set before we call getFrameRegister, otherwise we get
- // the wrong frame register.
+ // This needs to be set before we call getPtrSizedFrameRegister, otherwise
+ // we get the wrong frame register.
MachineFrameInfo *MFI = FuncInfo.MF->getFrameInfo();
MFI->setFrameAddressIsTaken(true);
const X86RegisterInfo *RegInfo = static_cast<const X86RegisterInfo *>(
TM.getSubtargetImpl()->getRegisterInfo());
- unsigned FrameReg = RegInfo->getFrameRegister(*(FuncInfo.MF));
+ unsigned FrameReg = RegInfo->getPtrSizedFrameRegister(*(FuncInfo.MF));
assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
(FrameReg == X86::EBP && VT == MVT::i32)) &&
"Invalid Frame Register!");
@@ -2900,13 +3028,32 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
MachineInstrBuilder MIB;
if (CalleeOp) {
// Register-indirect call.
- unsigned CallOpc = Is64Bit ? X86::CALL64r : X86::CALL32r;
+ unsigned CallOpc;
+ if (Subtarget->is64Bit()) {
+ // @LOCALMOD-BEGIN: zero extend the register like in the non-O0 case:
+ // http://reviews.llvm.org/D5355
+ // TODO: upstream this for x32 also (add a test).
+ if (Subtarget->isTarget64BitILP32()) {
+ unsigned CalleeOp32 = CalleeOp;
+ CalleeOp = createResultReg(&X86::GR64RegClass);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+ TII.get(TargetOpcode::SUBREG_TO_REG), CalleeOp)
+ .addImm(0).addReg(CalleeOp32).addImm(X86::sub_32bit);
+ }
+ // @LOCALMOD-END
+ CallOpc = X86::CALL64r;
+ } else
+ CallOpc = X86::CALL32r;
MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(CallOpc))
.addReg(CalleeOp);
} else {
// Direct call.
assert(GV && "Not a direct call");
- unsigned CallOpc = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32;
+ unsigned CallOpc;
+ if (Subtarget->is64Bit())
+ CallOpc = Subtarget->isTargetNaCl() ? X86::NACL_CG_CALL64pcrel32 : X86::CALL64pcrel32; // @LOCALMOD
+ else
+ CallOpc = X86::CALLpcrel32;
// See if we need any target-specific flags on the GV operand.
unsigned char OpFlags = 0;
« no previous file with comments | « lib/Target/X86/X86CallingConv.td ('k') | lib/Target/X86/X86FrameLowering.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698