From 79d4326b00e35359d38dd9b616840b27e4fc270e Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 24 Jan 2007 02:21:22 +0000 Subject: [PATCH] Various Thumb mode load / store isel bug fixes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33472 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelDAGToDAG.cpp | 51 ++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 42fbcfd670f..2307fe2bdf2 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -71,6 +71,9 @@ public: bool SelectThumbAddrModeRR(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset); + bool SelectThumbAddrModeRI5(SDOperand Op, SDOperand N, unsigned Scale, + SDOperand &Base, SDOperand &Offset, + SDOperand &OffImm); bool SelectThumbAddrModeS1(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset, SDOperand &OffImm); bool SelectThumbAddrModeS2(SDOperand Op, SDOperand N, SDOperand &Base, @@ -78,7 +81,7 @@ public: bool SelectThumbAddrModeS4(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset, SDOperand &OffImm); bool SelectThumbAddrModeSP(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Offset); + SDOperand &OffImm); bool SelectShifterOperandReg(SDOperand Op, SDOperand N, SDOperand &A, SDOperand &B, SDOperand &C); @@ -355,13 +358,16 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDOperand Op, SDOperand N, return true; } -static bool SelectThumbAddrModeRI5(SDOperand N, unsigned Scale, - TargetLowering &TLI, SelectionDAG *CurDAG, - SDOperand &Base, SDOperand &Offset, - SDOperand &OffImm) { - if (N.getOpcode() == ISD::FrameIndex) - return false; - +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDOperand Op, SDOperand N, + unsigned Scale, SDOperand &Base, + SDOperand &Offset, SDOperand &OffImm) { + if (Scale == 4) { + SDOperand TmpBase, TmpOffImm; + if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) + return false; // We want to select tLDRspi / tSTRspi instead. + } + if (N.getOpcode() != ISD::ADD) { Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N; Offset = CurDAG->getRegister(0, MVT::i32); @@ -392,29 +398,46 @@ static bool SelectThumbAddrModeRI5(SDOperand N, unsigned Scale, bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset, SDOperand &OffImm) { - return SelectThumbAddrModeRI5(N, 1, TLI, CurDAG, Base, Offset, OffImm); + return SelectThumbAddrModeRI5(Op, N, 1, Base, Offset, OffImm); } bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset, SDOperand &OffImm) { - return SelectThumbAddrModeRI5(N, 2, TLI, CurDAG, Base, Offset, OffImm); + return SelectThumbAddrModeRI5(Op, N, 2, Base, Offset, OffImm); } bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset, SDOperand &OffImm) { - return SelectThumbAddrModeRI5(N, 4, TLI, CurDAG, Base, Offset, OffImm); + return SelectThumbAddrModeRI5(Op, N, 4, Base, Offset, OffImm); } bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDOperand Op, SDOperand N, - SDOperand &Base, SDOperand &Offset) { + SDOperand &Base, SDOperand &OffImm) { if (N.getOpcode() == ISD::FrameIndex) { int FI = cast(N)->getIndex(); Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); - Offset = CurDAG->getTargetConstant(0, MVT::i32); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); return true; } + + if (N.getOpcode() == ISD::ADD && + N.getOperand(0).getOpcode() == ISD::FrameIndex) { + // If the RHS is + imm8 * scale, fold into addr mode. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getValue(); + if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. + RHSC >>= 2; + if (RHSC >= 0 && RHSC < 256) { + int FI = cast(N.getOperand(0))->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + } + } return false; } @@ -492,6 +515,8 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { CurDAG->getTargetConstant(0, MVT::i32)); } case ISD::MUL: + if (Subtarget->isThumb()) + break; if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { unsigned RHSV = C->getValue(); if (!RHSV) break;