llvm.org GIT mirror llvm / 6495f63
- More refactoring. This gets rid of all of the getOpcode calls. - This change also makes it possible to switch between ARM / Thumb on a per-function basis. - Fixed thumb2 routine which expand reg + arbitrary immediate. It was using using ARM so_imm logic. - Use movw and movt to do reg + imm when profitable. - Other code clean ups and minor optimizations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77300 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 11 years ago
17 changed file(s) with 639 addition(s) and 570 deletion(s). Raw diff Collapse all Expand all
273273 return V >> getThumbImmValShift(V);
274274 }
275275
276
276277 /// getT2SOImmValSplat - Return the 12-bit encoded representation
277278 /// if the specified value can be obtained by splatting the low 8 bits
278279 /// into every other byte or every byte of a 32-bit value. i.e.,
282283 /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3
283284 /// Return -1 if none of the above apply.
284285 /// See ARM Reference Manual A6.3.2.
285 static inline int getT2SOImmValSplat(unsigned V) {
286 static inline int getT2SOImmValSplatVal(unsigned V) {
286287 unsigned u, Vs, Imm;
287288 // control = 0
288289 if ((V & 0xffffff00) == 0)
306307 return -1;
307308 }
308309
309 /// getT2SOImmValRotate - Return the 12-bit encoded representation if the
310 /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
310311 /// specified value is a rotated 8-bit value. Return -1 if no rotation
311312 /// encoding is possible.
312313 /// See ARM Reference Manual A6.3.2.
313 static inline int getT2SOImmValRotate (unsigned V) {
314 static inline int getT2SOImmValRotateVal(unsigned V) {
314315 unsigned RotAmt = CountLeadingZeros_32(V);
315316 if (RotAmt >= 24)
316317 return -1;
328329 /// See ARM Reference Manual A6.3.2.
329330 static inline int getT2SOImmVal(unsigned Arg) {
330331 // If 'Arg' is an 8-bit splat, then get the encoded value.
331 int Splat = getT2SOImmValSplat(Arg);
332 int Splat = getT2SOImmValSplatVal(Arg);
332333 if (Splat != -1)
333334 return Splat;
334335
335336 // If 'Arg' can be handled with a single shifter_op return the value.
336 int Rot = getT2SOImmValRotate(Arg);
337 int Rot = getT2SOImmValRotateVal(Arg);
337338 if (Rot != -1)
338339 return Rot;
339340
3030 cl::desc("Enable ARM 2-addr to 3-addr conv"));
3131
3232 ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget &sti)
33 : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)),
34 STI(sti) {
33 : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)) {
3534 }
3635
3736 MachineInstr *
289288 const SmallVectorImpl &Cond) const {
290289 // FIXME this should probably have a DebugLoc argument
291290 DebugLoc dl = DebugLoc::getUnknownLoc();
292 int BOpc = !STI.isThumb()
293 ? ARM::B : (STI.isThumb2() ? ARM::t2B : ARM::tB);
294 int BccOpc = !STI.isThumb()
295 ? ARM::Bcc : (STI.isThumb2() ? ARM::t2Bcc : ARM::tBcc);
291
292 ARMFunctionInfo *AFI = MBB.getParent()->getInfo();
293 int BOpc = !AFI->isThumbFunction()
294 ? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB);
295 int BccOpc = !AFI->isThumbFunction()
296 ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
296297
297298 // Shouldn't be a fall through.
298299 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
784785 return false;
785786 }
786787
787 int ARMBaseInstrInfo::getMatchingCondBranchOpcode(int Opc) const {
788 int llvm::getMatchingCondBranchOpcode(int Opc) {
788789 if (Opc == ARM::B)
789790 return ARM::Bcc;
790791 else if (Opc == ARM::tB)
796797 return 0;
797798 }
798799
800
801 void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB,
802 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
803 unsigned DestReg, unsigned BaseReg, int NumBytes,
804 ARMCC::CondCodes Pred, unsigned PredReg,
805 const ARMBaseInstrInfo &TII) {
806 bool isSub = NumBytes < 0;
807 if (isSub) NumBytes = -NumBytes;
808
809 while (NumBytes) {
810 unsigned RotAmt = ARM_AM::getSOImmValRotate(NumBytes);
811 unsigned ThisVal = NumBytes & ARM_AM::rotr32(0xFF, RotAmt);
812 assert(ThisVal && "Didn't extract field correctly");
813
814 // We will handle these bits from offset, clear them.
815 NumBytes &= ~ThisVal;
816
817 assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?");
818
819 // Build the new ADD / SUB.
820 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;
821 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
822 .addReg(BaseReg, RegState::Kill).addImm(ThisVal)
823 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
824 BaseReg = DestReg;
825 }
826 }
827
828 int llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
829 unsigned FrameReg, int Offset,
830 const ARMBaseInstrInfo &TII) {
831 unsigned Opcode = MI.getOpcode();
832 const TargetInstrDesc &Desc = MI.getDesc();
833 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
834 bool isSub = false;
835
836 // Memory operands in inline assembly always use AddrMode2.
837 if (Opcode == ARM::INLINEASM)
838 AddrMode = ARMII::AddrMode2;
839
840 if (Opcode == ARM::ADDri) {
841 Offset += MI.getOperand(FrameRegIdx+1).getImm();
842 if (Offset == 0) {
843 // Turn it into a move.
844 MI.setDesc(TII.get(ARM::MOVr));
845 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
846 MI.RemoveOperand(FrameRegIdx+1);
847 return 0;
848 } else if (Offset < 0) {
849 Offset = -Offset;
850 isSub = true;
851 MI.setDesc(TII.get(ARM::SUBri));
852 }
853
854 // Common case: small offset, fits into instruction.
855 if (ARM_AM::getSOImmVal(Offset) != -1) {
856 // Replace the FrameIndex with sp / fp
857 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
858 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
859 return 0;
860 }
861
862 // Otherwise, pull as much of the immedidate into this ADDri/SUBri
863 // as possible.
864 unsigned RotAmt = ARM_AM::getSOImmValRotate(Offset);
865 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xFF, RotAmt);
866
867 // We will handle these bits from offset, clear them.
868 Offset &= ~ThisImmVal;
869
870 // Get the properly encoded SOImmVal field.
871 assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 &&
872 "Bit extraction didn't work?");
873 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
874 } else {
875 unsigned ImmIdx = 0;
876 int InstrOffs = 0;
877 unsigned NumBits = 0;
878 unsigned Scale = 1;
879 switch (AddrMode) {
880 case ARMII::AddrMode2: {
881 ImmIdx = FrameRegIdx+2;
882 InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm());
883 if (ARM_AM::getAM2Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
884 InstrOffs *= -1;
885 NumBits = 12;
886 break;
887 }
888 case ARMII::AddrMode3: {
889 ImmIdx = FrameRegIdx+2;
890 InstrOffs = ARM_AM::getAM3Offset(MI.getOperand(ImmIdx).getImm());
891 if (ARM_AM::getAM3Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
892 InstrOffs *= -1;
893 NumBits = 8;
894 break;
895 }
896 case ARMII::AddrMode5: {
897 ImmIdx = FrameRegIdx+1;
898 InstrOffs = ARM_AM::getAM5Offset(MI.getOperand(ImmIdx).getImm());
899 if (ARM_AM::getAM5Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
900 InstrOffs *= -1;
901 NumBits = 8;
902 Scale = 4;
903 break;
904 }
905 default:
906 llvm_unreachable("Unsupported addressing mode!");
907 break;
908 }
909
910 Offset += InstrOffs * Scale;
911 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
912 if (Offset < 0) {
913 Offset = -Offset;
914 isSub = true;
915 }
916
917 // Attempt to fold address comp. if opcode has offset bits
918 if (NumBits > 0) {
919 // Common case: small offset, fits into instruction.
920 MachineOperand &ImmOp = MI.getOperand(ImmIdx);
921 int ImmedOffset = Offset / Scale;
922 unsigned Mask = (1 << NumBits) - 1;
923 if ((unsigned)Offset <= Mask * Scale) {
924 // Replace the FrameIndex with sp
925 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
926 if (isSub)
927 ImmedOffset |= 1 << NumBits;
928 ImmOp.ChangeToImmediate(ImmedOffset);
929 return 0;
930 }
931
932 // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
933 ImmedOffset = ImmedOffset & Mask;
934 if (isSub)
935 ImmedOffset |= 1 << NumBits;
936 ImmOp.ChangeToImmediate(ImmedOffset);
937 Offset &= ~(Mask*Scale);
938 }
939 }
940
941 return (isSub) ? -Offset : Offset;
942 }
154154 I_BitShift = 25,
155155 CondShift = 28
156156 };
157
158 /// ARMII::Op - Holds all of the instruction types required by
159 /// target specific instruction and register code. ARMBaseInstrInfo
160 /// and subclasses should return a specific opcode that implements
161 /// the instruction type.
162 ///
163 enum Op {
164 ADDri,
165 MOVr,
166 SUBri
167 };
168 }
169
170 static inline
171 const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) {
172 return MIB.addImm((int64_t)ARMCC::AL).addReg(0);
173 }
174
175 static inline
176 const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
177 return MIB.addReg(0);
178 }
179
180 static inline
181 const MachineInstrBuilder &AddDefaultT1CC(const MachineInstrBuilder &MIB) {
182 return MIB.addReg(ARM::CPSR);
183157 }
184158
185159 class ARMBaseInstrInfo : public TargetInstrInfoImpl {
186 const ARMSubtarget &STI;
187
188160 protected:
189161 // Can be only subclassed.
190162 explicit ARMBaseInstrInfo(const ARMSubtarget &sti);
192164 // Return the non-pre/post incrementing version of 'Opc'. Return 0
193165 // if there is not such an opcode.
194166 virtual unsigned getUnindexedOpcode(unsigned Opc) const =0;
195
196 // Return the opcode that implements 'Op', or 0 if no opcode
197 virtual unsigned getOpcode(ARMII::Op Op) const =0;
198167
199168 // Return true if the block does not fall through.
200169 virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const =0;
285254 const SmallVectorImpl &Ops,
286255 MachineInstr* LoadMI) const;
287256
288 private:
289 bool isUncondBranchOpcode(int Opc) const {
290 return Opc == ARM::B || Opc == ARM::tB || Opc == ARM::t2B;
291 }
292
293 bool isCondBranchOpcode(int Opc) const {
294 return Opc == ARM::Bcc || Opc == ARM::tBcc || Opc == ARM::t2Bcc;
295 }
296
297 bool isJumpTableBranchOpcode(int Opc) const {
298 return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm || Opc == ARM::BR_JTadd ||
299 Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT;
300 }
301
302 int getMatchingCondBranchOpcode(int Opc) const;
303257 };
304 }
258
259 static inline
260 const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) {
261 return MIB.addImm((int64_t)ARMCC::AL).addReg(0);
262 }
263
264 static inline
265 const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
266 return MIB.addReg(0);
267 }
268
269 static inline
270 const MachineInstrBuilder &AddDefaultT1CC(const MachineInstrBuilder &MIB) {
271 return MIB.addReg(ARM::CPSR);
272 }
273
274 static inline
275 bool isUncondBranchOpcode(int Opc) {
276 return Opc == ARM::B || Opc == ARM::tB || Opc == ARM::t2B;
277 }
278
279 static inline
280 bool isCondBranchOpcode(int Opc) {
281 return Opc == ARM::Bcc || Opc == ARM::tBcc || Opc == ARM::t2Bcc;
282 }
283
284 static inline
285 bool isJumpTableBranchOpcode(int Opc) {
286 return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm || Opc == ARM::BR_JTadd ||
287 Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT;
288 }
289
290 int getMatchingCondBranchOpcode(int Opc);
291
292 /// emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of
293 /// instructions to materializea destreg = basereg + immediate in ARM / Thumb2
294 /// code.
295 void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
296 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
297 unsigned DestReg, unsigned BaseReg, int NumBytes,
298 ARMCC::CondCodes Pred, unsigned PredReg,
299 const ARMBaseInstrInfo &TII);
300
301 void emitT2RegPlusImmediate(MachineBasicBlock &MBB,
302 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
303 unsigned DestReg, unsigned BaseReg, int NumBytes,
304 ARMCC::CondCodes Pred, unsigned PredReg,
305 const ARMBaseInstrInfo &TII);
306
307
308 /// rewriteARMFrameIndex / rewriteT2FrameIndex -
309 /// Rewrite MI to access 'Offset' bytes from the FP. Return the offset that
310 /// could not be handled directly in MI.
311 int rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
312 unsigned FrameReg, int Offset,
313 const ARMBaseInstrInfo &TII);
314
315 int rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
316 unsigned FrameReg, int Offset,
317 const ARMBaseInstrInfo &TII);
318
319 } // End llvm namespace
305320
306321 #endif
134134 : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
135135 TII(tii), STI(sti),
136136 FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11) {
137 }
138
139 unsigned ARMBaseRegisterInfo::
140 getOpcode(int Op) const {
141 return TII.getOpcode((ARMII::Op)Op);
142137 }
143138
144139 const unsigned*
880875 return 0;
881876 }
882877
883 // FIXME: Dup in ARMBaseInstrInfo.cpp
884 static inline
885 const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) {
886 return MIB.addImm((int64_t)ARMCC::AL).addReg(0);
887 }
888
889 static inline
890 const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
891 return MIB.addReg(0);
892 }
893
894878 /// emitLoadConstPool - Emits a load from constpool to materialize the
895879 /// specified immediate.
896880 void ARMBaseRegisterInfo::
935919 return !MF.getFrameInfo()->hasVarSizedObjects();
936920 }
937921
938 /// emitARMRegPlusImmediate - Emits a series of instructions to materialize
939 /// a destreg = basereg + immediate in ARM code.
940 static
941 void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
942 MachineBasicBlock::iterator &MBBI,
943 unsigned DestReg, unsigned BaseReg, int NumBytes,
944 ARMCC::CondCodes Pred, unsigned PredReg,
945 const ARMBaseInstrInfo &TII,
946 DebugLoc dl) {
947 bool isSub = NumBytes < 0;
948 if (isSub) NumBytes = -NumBytes;
949
950 while (NumBytes) {
951 unsigned RotAmt = ARM_AM::getSOImmValRotate(NumBytes);
952 unsigned ThisVal = NumBytes & ARM_AM::rotr32(0xFF, RotAmt);
953 assert(ThisVal && "Didn't extract field correctly");
954
955 // We will handle these bits from offset, clear them.
956 NumBytes &= ~ThisVal;
957
958 assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?");
959
960 // Build the new ADD / SUB.
961 unsigned Opc = TII.getOpcode(isSub ? ARMII::SUBri : ARMII::ADDri);
962 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
963 .addReg(BaseReg, RegState::Kill).addImm(ThisVal)
964 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
965 BaseReg = DestReg;
966 }
967 }
968
969922 static void
970 emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
971 const ARMBaseInstrInfo &TII, DebugLoc dl,
923 emitSPUpdate(bool isARM,
924 MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
925 DebugLoc dl, const ARMBaseInstrInfo &TII,
972926 int NumBytes,
973927 ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) {
974 emitARMRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes,
975 Pred, PredReg, TII, dl);
976 }
928 if (isARM)
929 emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes,
930 Pred, PredReg, TII);
931 else
932 emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes,
933 Pred, PredReg, TII);
934 }
935
977936
978937 void ARMBaseRegisterInfo::
979938 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
992951 unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
993952 Amount = (Amount+Align-1)/Align*Align;
994953
954 ARMFunctionInfo *AFI = MF.getInfo();
955 assert(!AFI->isThumb1OnlyFunction() &&
956 "This eliminateCallFramePseudoInstr does not suppor Thumb1!");
957 bool isARM = !AFI->isThumbFunction();
958
995959 // Replace the pseudo instruction with a new instruction...
996960 unsigned Opc = Old->getOpcode();
997961 ARMCC::CondCodes Pred = (ARMCC::CondCodes)Old->getOperand(1).getImm();
962 // FIXME: Thumb2 version of ADJCALLSTACKUP and ADJCALLSTACKDOWN?
998963 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
999964 // Note: PredReg is operand 2 for ADJCALLSTACKDOWN.
1000965 unsigned PredReg = Old->getOperand(2).getReg();
1001 emitSPUpdate(MBB, I, TII, dl, -Amount, Pred, PredReg);
966 emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, Pred, PredReg);
1002967 } else {
1003968 // Note: PredReg is operand 3 for ADJCALLSTACKUP.
1004969 unsigned PredReg = Old->getOperand(3).getReg();
1005970 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
1006 emitSPUpdate(MBB, I, TII, dl, Amount, Pred, PredReg);
971 emitSPUpdate(isARM, MBB, I, dl, TII, Amount, Pred, PredReg);
1007972 }
1008973 }
1009974 }
1017982 unsigned findScratchRegister(RegScavenger *RS, const TargetRegisterClass *RC,
1018983 ARMFunctionInfo *AFI) {
1019984 unsigned Reg = RS ? RS->FindUnusedReg(RC, true) : (unsigned) ARM::R12;
1020 assert (!AFI->isThumb1OnlyFunction());
985 assert(!AFI->isThumb1OnlyFunction());
1021986 if (Reg == 0)
1022987 // Try a already spilled CS register.
1023988 Reg = RS->FindUnusedReg(RC, AFI->getSpilledCSRegisters());
1025990 return Reg;
1026991 }
1027992
1028 int ARMBaseRegisterInfo::
1029 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
1030 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
1031 unsigned FrameReg, int Offset) const
1032 {
1033 unsigned Opcode = MI.getOpcode();
1034 const TargetInstrDesc &Desc = MI.getDesc();
1035 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
1036 bool isSub = false;
1037
1038 // Memory operands in inline assembly always use AddrMode2.
1039 if (Opcode == ARM::INLINEASM)
1040 AddrMode = ARMII::AddrMode2;
1041
1042 if (Opcode == ADDriOpc) {
1043 Offset += MI.getOperand(FrameRegIdx+1).getImm();
1044 if (Offset == 0) {
1045 // Turn it into a move.
1046 MI.setDesc(TII.get(MOVOpc));
1047 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
1048 MI.RemoveOperand(FrameRegIdx+1);
1049 return 0;
1050 } else if (Offset < 0) {
1051 Offset = -Offset;
1052 isSub = true;
1053 MI.setDesc(TII.get(SUBriOpc));
1054 }
1055
1056 // Common case: small offset, fits into instruction.
1057 if (ARM_AM::getSOImmVal(Offset) != -1) {
1058 // Replace the FrameIndex with sp / fp
1059 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
1060 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
1061 return 0;
1062 }
1063
1064 // Otherwise, pull as much of the immedidate into this ADDri/SUBri
1065 // as possible.
1066 unsigned RotAmt = ARM_AM::getSOImmValRotate(Offset);
1067 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xFF, RotAmt);
1068
1069 // We will handle these bits from offset, clear them.
1070 Offset &= ~ThisImmVal;
1071
1072 // Get the properly encoded SOImmVal field.
1073 assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 &&
1074 "Bit extraction didn't work?");
1075 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
1076 } else {
1077 unsigned ImmIdx = 0;
1078 int InstrOffs = 0;
1079 unsigned NumBits = 0;
1080 unsigned Scale = 1;
1081 switch (AddrMode) {
1082 case ARMII::AddrMode2: {
1083 ImmIdx = FrameRegIdx+2;
1084 InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm());
1085 if (ARM_AM::getAM2Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1086 InstrOffs *= -1;
1087 NumBits = 12;
1088 break;
1089 }
1090 case ARMII::AddrMode3: {
1091 ImmIdx = FrameRegIdx+2;
1092 InstrOffs = ARM_AM::getAM3Offset(MI.getOperand(ImmIdx).getImm());
1093 if (ARM_AM::getAM3Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1094 InstrOffs *= -1;
1095 NumBits = 8;
1096 break;
1097 }
1098 case ARMII::AddrMode5: {
1099 ImmIdx = FrameRegIdx+1;
1100 InstrOffs = ARM_AM::getAM5Offset(MI.getOperand(ImmIdx).getImm());
1101 if (ARM_AM::getAM5Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub)
1102 InstrOffs *= -1;
1103 NumBits = 8;
1104 Scale = 4;
1105 break;
1106 }
1107 default:
1108 llvm_unreachable("Unsupported addressing mode!");
1109 break;
1110 }
1111
1112 Offset += InstrOffs * Scale;
1113 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
1114 if (Offset < 0) {
1115 Offset = -Offset;
1116 isSub = true;
1117 }
1118
1119 // Attempt to fold address comp. if opcode has offset bits
1120 if (NumBits > 0) {
1121 // Common case: small offset, fits into instruction.
1122 MachineOperand &ImmOp = MI.getOperand(ImmIdx);
1123 int ImmedOffset = Offset / Scale;
1124 unsigned Mask = (1 << NumBits) - 1;
1125 if ((unsigned)Offset <= Mask * Scale) {
1126 // Replace the FrameIndex with sp
1127 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
1128 if (isSub)
1129 ImmedOffset |= 1 << NumBits;
1130 ImmOp.ChangeToImmediate(ImmedOffset);
1131 return 0;
1132 }
1133
1134 // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
1135 ImmedOffset = ImmedOffset & Mask;
1136 if (isSub)
1137 ImmedOffset |= 1 << NumBits;
1138 ImmOp.ChangeToImmediate(ImmedOffset);
1139 Offset &= ~(Mask*Scale);
1140 }
1141 }
1142
1143 return (isSub) ? -Offset : Offset;
1144 }
1145
1146 void ARMBaseRegisterInfo::
1147 eliminateFrameIndexImpl(MachineBasicBlock::iterator II,
1148 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
1149 int SPAdj, RegScavenger *RS) const {
993 void
994 ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
995 int SPAdj, RegScavenger *RS) const {
1150996 unsigned i = 0;
1151997 MachineInstr &MI = *II;
1152998 MachineBasicBlock &MBB = *MI.getParent();
1153999 MachineFunction &MF = *MBB.getParent();
11541000 ARMFunctionInfo *AFI = MF.getInfo();
1155 DebugLoc dl = MI.getDebugLoc();
1001 assert(!AFI->isThumb1OnlyFunction() &&
1002 "This eliminateFrameIndex does not suppor Thumb1!");
11561003
11571004 while (!MI.getOperand(i).isFI()) {
11581005 ++i;
11791026 }
11801027
11811028 // modify MI as necessary to handle as much of 'Offset' as possible
1182 Offset = rewriteFrameIndex(MI, i, MOVOpc,ADDriOpc,SUBriOpc, FrameReg, Offset);
1029 if (!AFI->isThumbFunction())
1030 Offset = rewriteARMFrameIndex(MI, i, FrameReg, Offset, TII);
1031 else {
1032 assert(AFI->isThumb2Function());
1033 Offset = rewriteT2FrameIndex(MI, i, FrameReg, Offset, TII);
1034 }
11831035 if (Offset == 0)
11841036 return;
11851037
12001052 ARMCC::CondCodes Pred = (PIdx == -1)
12011053 ? ARMCC::AL : (ARMCC::CondCodes)MI.getOperand(PIdx).getImm();
12021054 unsigned PredReg = (PIdx == -1) ? 0 : MI.getOperand(PIdx+1).getReg();
1203 emitARMRegPlusImmediate(MBB, II, ScratchReg, FrameReg,
1204 Offset, Pred, PredReg, TII, dl);
1055 if (!AFI->isThumbFunction())
1056 emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg,
1057 Offset, Pred, PredReg, TII);
1058 else {
1059 assert(AFI->isThumb2Function());
1060 emitT2RegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg,
1061 Offset, Pred, PredReg, TII);
1062 }
12051063 MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
12061064 }
12071065
12481106 MachineBasicBlock::iterator MBBI = MBB.begin();
12491107 MachineFrameInfo *MFI = MF.getFrameInfo();
12501108 ARMFunctionInfo *AFI = MF.getInfo();
1109 assert(!AFI->isThumb1OnlyFunction() &&
1110 "This emitPrologue does not suppor Thumb1!");
1111 bool isARM = !AFI->isThumbFunction();
12511112 unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
12521113 unsigned NumBytes = MFI->getStackSize();
12531114 const std::vector &CSI = MFI->getCalleeSavedInfo();
12601121 int FramePtrSpillFI = 0;
12611122
12621123 if (VARegSaveSize)
1263 emitSPUpdate(MBB, MBBI, TII, dl, -VARegSaveSize);
1124 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize);
12641125
12651126 if (!AFI->hasStackFrame()) {
12661127 if (NumBytes != 0)
1267 emitSPUpdate(MBB, MBBI, TII, dl, -NumBytes);
1128 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
12681129 return;
12691130 }
12701131
13031164 }
13041165
13051166 // Build the new SUBri to adjust SP for integer callee-save spill area 1.
1306 emitSPUpdate(MBB, MBBI, TII, dl, -GPRCS1Size);
1167 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS1Size);
13071168 movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, ARM::t2STRi12, 1, STI);
13081169
13091170 // Darwin ABI requires FP to point to the stack slot that contains the
13101171 // previous FP.
13111172 if (STI.isTargetDarwin() || hasFP(MF)) {
1173 unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri;
13121174 MachineInstrBuilder MIB =
1313 BuildMI(MBB, MBBI, dl, TII.get(getOpcode(ARMII::ADDri)), FramePtr)
1175 BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr)
13141176 .addFrameIndex(FramePtrSpillFI).addImm(0);
13151177 AddDefaultCC(AddDefaultPred(MIB));
13161178 }
13171179
13181180 // Build the new SUBri to adjust SP for integer callee-save spill area 2.
1319 emitSPUpdate(MBB, MBBI, TII, dl, -GPRCS2Size);
1181 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -GPRCS2Size);
13201182
13211183 // Build the new SUBri to adjust SP for FP callee-save spill area.
13221184 movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, ARM::t2STRi12, 2, STI);
1323 emitSPUpdate(MBB, MBBI, TII, dl, -DPRCSSize);
1185 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRCSSize);
13241186
13251187 // Determine starting offsets of spill areas.
13261188 unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
13351197 if (NumBytes) {
13361198 // Insert it after all the callee-save spills.
13371199 movePastCSLoadStoreOps(MBB, MBBI, ARM::FSTD, 0, 3, STI);
1338 emitSPUpdate(MBB, MBBI, TII, dl, -NumBytes);
1200 emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
13391201 }
13401202
13411203 if (STI.isTargetELF() && hasFP(MF)) {
13671229
13681230 void ARMBaseRegisterInfo::
13691231 emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
1370 assert(!STI.isThumb1Only() &&
1371 "This emitEpilogue should not be executed for Thumb1!");
1372
13731232 MachineBasicBlock::iterator MBBI = prior(MBB.end());
13741233 assert(MBBI->getDesc().isReturn() &&
13751234 "Can only insert epilog into returning blocks");
13761235 DebugLoc dl = MBBI->getDebugLoc();
13771236 MachineFrameInfo *MFI = MF.getFrameInfo();
13781237 ARMFunctionInfo *AFI = MF.getInfo();
1238 assert(!AFI->isThumb1OnlyFunction() &&
1239 "This emitEpilogue does not suppor Thumb1!");
1240 bool isARM = !AFI->isThumbFunction();
1241
13791242 unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize();
13801243 int NumBytes = (int)MFI->getStackSize();
13811244
13821245 if (!AFI->hasStackFrame()) {
13831246 if (NumBytes != 0)
1384 emitSPUpdate(MBB, MBBI, TII, dl, NumBytes);
1247 emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
13851248 } else {
13861249 // Unwind MBBI to point to first LDR / FLDD.
13871250 const unsigned *CSRegs = getCalleeSavedRegs();
14081271 AFI->getDPRCalleeSavedAreaSize() ||
14091272 AFI->getDPRCalleeSavedAreaOffset()||
14101273 hasFP(MF)) {
1411 if (NumBytes)
1412 BuildMI(MBB, MBBI, dl, TII.get(getOpcode(ARMII::SUBri)), ARM::SP)
1274 if (NumBytes) {
1275 unsigned SUBriOpc = isARM ? ARM::SUBri : ARM::t2SUBri;
1276 BuildMI(MBB, MBBI, dl, TII.get(SUBriOpc), ARM::SP)
14131277 .addReg(FramePtr)
14141278 .addImm(NumBytes)
14151279 .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
1416 else
1417 BuildMI(MBB, MBBI, dl, TII.get(getOpcode(ARMII::MOVr)), ARM::SP)
1280 } else {
1281 // Thumb2 or ARM.
1282 unsigned MOVrOpc = isARM ? ARM::MOVr : ARM::t2MOVr;
1283 BuildMI(MBB, MBBI, dl, TII.get(MOVrOpc), ARM::SP)
14181284 .addReg(FramePtr)
14191285 .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
1286 }
14201287 }
1421 } else if (NumBytes) {
1422 emitSPUpdate(MBB, MBBI, TII, dl, NumBytes);
1423 }
1288 } else if (NumBytes)
1289 emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
14241290
14251291 // Move SP to start of integer callee save spill area 2.
14261292 movePastCSLoadStoreOps(MBB, MBBI, ARM::FLDD, 0, 3, STI);
1427 emitSPUpdate(MBB, MBBI, TII, dl, AFI->getDPRCalleeSavedAreaSize());
1293 emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedAreaSize());
14281294
14291295 // Move SP to start of integer callee save spill area 1.
14301296 movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, ARM::t2LDRi12, 2, STI);
1431 emitSPUpdate(MBB, MBBI, TII, dl, AFI->getGPRCalleeSavedArea2Size());
1297 emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea2Size());
14321298
14331299 // Move SP to SP upon entry to the function.
14341300 movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, ARM::t2LDRi12, 1, STI);
1435 emitSPUpdate(MBB, MBBI, TII, dl, AFI->getGPRCalleeSavedArea1Size());
1301 emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedArea1Size());
14361302 }
14371303
14381304 if (VARegSaveSize)
1439 emitSPUpdate(MBB, MBBI, TII, dl, VARegSaveSize);
1440
1305 emitSPUpdate(isARM, MBB, MBBI, dl, TII, VARegSaveSize);
14411306 }
14421307
14431308 #include "ARMGenRegisterInfo.inc"
125125 MachineBasicBlock &MBB,
126126 MachineBasicBlock::iterator I) const;
127127
128 // rewrite MI to access 'Offset' bytes from the FP. Return the offset that
129 // could not be handled directly in MI.
130 virtual int
131 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
132 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
133 unsigned FrameReg, int Offset) const;
134
135 virtual void
136 eliminateFrameIndex(MachineBasicBlock::iterator II,
137 int SPAdj, RegScavenger *RS = NULL) const {
138 eliminateFrameIndexImpl(II, ARM::MOVr, ARM::ADDri, ARM::SUBri, SPAdj, RS);
139 }
128 virtual void eliminateFrameIndex(MachineBasicBlock::iterator II,
129 int SPAdj, RegScavenger *RS = NULL) const;
140130
141131 virtual void emitPrologue(MachineFunction &MF) const;
142132 virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
143
144 protected:
145 void
146 eliminateFrameIndexImpl(MachineBasicBlock::iterator II,
147 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
148 int SPAdj, RegScavenger *RS = NULL) const;
149133
150134 private:
151135 unsigned getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const;
6161 return 0;
6262 }
6363
64 unsigned ARMInstrInfo::
65 getOpcode(ARMII::Op Op) const {
66 switch (Op) {
67 case ARMII::ADDri: return ARM::ADDri;
68 case ARMII::MOVr: return ARM::MOVr;
69 case ARMII::SUBri: return ARM::SUBri;
70 default:
71 break;
72 }
73
74 return 0;
75 }
76
7764 bool ARMInstrInfo::
7865 BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
7966 if (MBB.empty()) return false;
3131 // if there is not such an opcode.
3232 unsigned getUnindexedOpcode(unsigned Opc) const;
3333
34 // Return the opcode that implements 'Op', or 0 if no opcode
35 unsigned getOpcode(ARMII::Op Op) const;
36
3734 // Return true if the block does not fall through.
3835 bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
3936
427427 (ins i32imm:$label, i32imm:$id, pred:$p),
428428 "adr$p.w $dst, #${label}_${id:no_hash}", []>;
429429
430 // ADD rd, sp, #so_imm
431 def t2ADDrSPi : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm),
432 "add.w $dst, $sp, $imm",
433 []>;
434
435 // ADD rd, sp, #imm12
436 def t2ADDrSPi12 : T2XI<(outs GPR:$dst), (ins GPR:$sp, i32imm:$imm),
437 "addw $dst, $sp, $imm",
438 []>;
439
440 def t2ADDrSPs : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs),
441 "addw $dst, $sp, $rhs",
442 []>;
443
444
445430 //===----------------------------------------------------------------------===//
446431 // Load / store Instructions.
447432 //
2626 }
2727
2828 unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
29 return 0;
30 }
31
32 unsigned Thumb1InstrInfo::getOpcode(ARMII::Op Op) const {
33 switch (Op) {
34 case ARMII::ADDri: return ARM::tADDi8;
35 case ARMII::MOVr: return ARM::tMOVr;
36 case ARMII::SUBri: return ARM::tSUBi8;
37 default:
38 break;
39 }
40
4129 return 0;
4230 }
4331
2929 // Return the non-pre/post incrementing version of 'Opc'. Return 0
3030 // if there is not such an opcode.
3131 unsigned getUnindexedOpcode(unsigned Opc) const;
32
33 // Return the opcode that implements 'Op', or 0 if no opcode
34 unsigned getOpcode(ARMII::Op Op) const;
3532
3633 // Return true if the block does not fall through.
3734 bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
387387
388388 int Thumb1RegisterInfo::
389389 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
390 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
391 unsigned FrameReg, int Offset) const
390 unsigned FrameReg, int Offset,
391 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc) const
392392 {
393393 // if/when eliminateFrameIndex() conforms with ARMBaseRegisterInfo
394394 // version then can pull out Thumb1 specific parts here
5050 // rewrite MI to access 'Offset' bytes from the FP. Return the offset that
5151 // could not be handled directly in MI.
5252 int rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
53 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
54 unsigned FrameReg, int Offset) const;
53 unsigned FrameReg, int Offset,
54 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc) const;
5555
5656 void eliminateFrameIndex(MachineBasicBlock::iterator II,
5757 int SPAdj, RegScavenger *RS = NULL) const;
1212
1313 #include "ARMInstrInfo.h"
1414 #include "ARM.h"
15 #include "ARMAddressingModes.h"
1516 #include "ARMGenInstrInfo.inc"
1617 #include "ARMMachineFunctionInfo.h"
1718 #include "llvm/CodeGen/MachineFrameInfo.h"
2728
2829 unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
2930 // FIXME
30 return 0;
31 }
32
33 unsigned Thumb2InstrInfo::getOpcode(ARMII::Op Op) const {
34 switch (Op) {
35 case ARMII::ADDri: return ARM::t2ADDri;
36 case ARMII::MOVr: return ARM::t2MOVr;
37 case ARMII::SUBri: return ARM::t2SUBri;
38 default:
39 break;
40 }
41
4231 return 0;
4332 }
4433
123112
124113 ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC);
125114 }
115
116
117 void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
118 MachineBasicBlock::iterator &MBBI, DebugLoc dl,
119 unsigned DestReg, unsigned BaseReg, int NumBytes,
120 ARMCC::CondCodes Pred, unsigned PredReg,
121 const ARMBaseInstrInfo &TII) {
122 bool isSub = NumBytes < 0;
123 if (isSub) NumBytes = -NumBytes;
124
125 // If profitable, use a movw or movt to materialize the offset.
126 // FIXME: Use the scavenger to grab a scratch register.
127 if (DestReg != ARM::SP && DestReg != BaseReg &&
128 NumBytes >= 4096 &&
129 ARM_AM::getT2SOImmVal(NumBytes) == -1) {
130 bool Fits = false;
131 if (NumBytes < 65536) {
132 // Use a movw to materialize the 16-bit constant.
133 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
134 .addImm(NumBytes)
135 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
136 Fits = true;
137 } else if ((NumBytes & 0xffff) == 0) {
138 // Use a movt to materialize the 32-bit constant.
139 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)
140 .addReg(DestReg)
141 .addImm(NumBytes >> 16)
142 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
143 Fits = true;
144 }
145
146 if (Fits) {
147 if (isSub) {
148 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)
149 .addReg(BaseReg, RegState::Kill)
150 .addReg(DestReg, RegState::Kill)
151 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
152 } else {
153 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
154 .addReg(DestReg, RegState::Kill)
155 .addReg(BaseReg, RegState::Kill)
156 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
157 }
158 return;
159 }
160 }
161
162 while (NumBytes) {
163 unsigned Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri;
164 unsigned ThisVal = NumBytes;
165 if (ARM_AM::getT2SOImmVal(NumBytes) != -1) {
166 NumBytes = 0;
167 } else if (ThisVal < 4096) {
168 Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
169 NumBytes = 0;
170 } else {
171 // FIXME: Move this to ARMAddressingModes.h?
172 unsigned RotAmt = CountLeadingZeros_32(ThisVal);
173 ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt);
174 NumBytes &= ~ThisVal;
175 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
176 "Bit extraction didn't work?");
177 }
178
179 // Build the new ADD / SUB.
180 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
181 .addReg(BaseReg, RegState::Kill).addImm(ThisVal)
182 .addImm((unsigned)Pred).addReg(PredReg).addReg(0);
183 BaseReg = DestReg;
184 }
185 }
186
187 static unsigned
188 negativeOffsetOpcode(unsigned opcode)
189 {
190 switch (opcode) {
191 case ARM::t2LDRi12: return ARM::t2LDRi8;
192 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
193 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
194 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
195 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
196 case ARM::t2STRi12: return ARM::t2STRi8;
197 case ARM::t2STRBi12: return ARM::t2STRBi8;
198 case ARM::t2STRHi12: return ARM::t2STRHi8;
199
200 case ARM::t2LDRi8:
201 case ARM::t2LDRHi8:
202 case ARM::t2LDRBi8:
203 case ARM::t2LDRSHi8:
204 case ARM::t2LDRSBi8:
205 case ARM::t2STRi8:
206 case ARM::t2STRBi8:
207 case ARM::t2STRHi8:
208 return opcode;
209
210 default:
211 break;
212 }
213
214 return 0;
215 }
216
217 static unsigned
218 positiveOffsetOpcode(unsigned opcode)
219 {
220 switch (opcode) {
221 case ARM::t2LDRi8: return ARM::t2LDRi12;
222 case ARM::t2LDRHi8: return ARM::t2LDRHi12;
223 case ARM::t2LDRBi8: return ARM::t2LDRBi12;
224 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
225 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
226 case ARM::t2STRi8: return ARM::t2STRi12;
227 case ARM::t2STRBi8: return ARM::t2STRBi12;
228 case ARM::t2STRHi8: return ARM::t2STRHi12;
229
230 case ARM::t2LDRi12:
231 case ARM::t2LDRHi12:
232 case ARM::t2LDRBi12:
233 case ARM::t2LDRSHi12:
234 case ARM::t2LDRSBi12:
235 case ARM::t2STRi12:
236 case ARM::t2STRBi12:
237 case ARM::t2STRHi12:
238 return opcode;
239
240 default:
241 break;
242 }
243
244 return 0;
245 }
246
247 static unsigned
248 immediateOffsetOpcode(unsigned opcode)
249 {
250 switch (opcode) {
251 case ARM::t2LDRs: return ARM::t2LDRi12;
252 case ARM::t2LDRHs: return ARM::t2LDRHi12;
253 case ARM::t2LDRBs: return ARM::t2LDRBi12;
254 case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
255 case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
256 case ARM::t2STRs: return ARM::t2STRi12;
257 case ARM::t2STRBs: return ARM::t2STRBi12;
258 case ARM::t2STRHs: return ARM::t2STRHi12;
259
260 case ARM::t2LDRi12:
261 case ARM::t2LDRHi12:
262 case ARM::t2LDRBi12:
263 case ARM::t2LDRSHi12:
264 case ARM::t2LDRSBi12:
265 case ARM::t2STRi12:
266 case ARM::t2STRBi12:
267 case ARM::t2STRHi12:
268 case ARM::t2LDRi8:
269 case ARM::t2LDRHi8:
270 case ARM::t2LDRBi8:
271 case ARM::t2LDRSHi8:
272 case ARM::t2LDRSBi8:
273 case ARM::t2STRi8:
274 case ARM::t2STRBi8:
275 case ARM::t2STRHi8:
276 return opcode;
277
278 default:
279 break;
280 }
281
282 return 0;
283 }
284
285 int llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
286 unsigned FrameReg, int Offset,
287 const ARMBaseInstrInfo &TII) {
288 unsigned Opcode = MI.getOpcode();
289 unsigned NewOpc = Opcode;
290 const TargetInstrDesc &Desc = MI.getDesc();
291 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
292 bool isSub = false;
293
294 // Memory operands in inline assembly always use AddrModeT2_i12.
295 if (Opcode == ARM::INLINEASM)
296 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
297
298 if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
299 Offset += MI.getOperand(FrameRegIdx+1).getImm();
300 if (Offset == 0) {
301 // Turn it into a move.
302 MI.setDesc(TII.get(ARM::t2MOVr));
303 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
304 MI.RemoveOperand(FrameRegIdx+1);
305 return 0;
306 }
307
308 if (Offset < 0) {
309 Offset = -Offset;
310 isSub = true;
311 MI.setDesc(TII.get(ARM::t2SUBri));
312 }
313
314 // Common case: small offset, fits into instruction.
315 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
316 NewOpc = isSub ? ARM::t2SUBri : ARM::t2ADDri;
317 if (NewOpc != Opcode)
318 MI.setDesc(TII.get(NewOpc));
319 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
320 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
321 return 0;
322 }
323 // Another common case: imm12.
324 if (Offset < 4096) {
325 NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
326 if (NewOpc != Opcode)
327 MI.setDesc(TII.get(NewOpc));
328 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
329 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
330 return 0;
331 }
332
333 // Otherwise, extract 8 adjacent bits from the immediate into this
334 // t2ADDri/t2SUBri.
335 unsigned RotAmt = CountLeadingZeros_32(Offset);
336 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt);
337
338 // We will handle these bits from offset, clear them.
339 Offset &= ~ThisImmVal;
340
341 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
342 "Bit extraction didn't work?");
343 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
344 } else {
345 // AddrModeT2_so cannot handle any offset. If there is no offset
346 // register then we change to an immediate version.
347 NewOpc = Opcode;
348 if (AddrMode == ARMII::AddrModeT2_so) {
349 unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg();
350 if (OffsetReg != 0) {
351 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
352 return Offset;
353 }
354
355 MI.RemoveOperand(FrameRegIdx+1);
356 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
357 NewOpc = immediateOffsetOpcode(Opcode);
358 AddrMode = ARMII::AddrModeT2_i12;
359 }
360
361 unsigned NumBits = 0;
362 unsigned Scale = 1;
363 if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) {
364 // i8 supports only negative, and i12 supports only positive, so
365 // based on Offset sign convert Opcode to the appropriate
366 // instruction
367 Offset += MI.getOperand(FrameRegIdx+1).getImm();
368 if (Offset < 0) {
369 NewOpc = negativeOffsetOpcode(Opcode);
370 NumBits = 8;
371 isSub = true;
372 Offset = -Offset;
373 } else {
374 NewOpc = positiveOffsetOpcode(Opcode);
375 NumBits = 12;
376 }
377 } else {
378 // VFP address modes.
379 assert(AddrMode == ARMII::AddrMode5);
380 int InstrOffs=ARM_AM::getAM5Offset(MI.getOperand(FrameRegIdx+1).getImm());
381 if (ARM_AM::getAM5Op(MI.getOperand(FrameRegIdx+1).getImm()) ==ARM_AM::sub)
382 InstrOffs *= -1;
383 NumBits = 8;
384 Scale = 4;
385 Offset += InstrOffs * 4;
386 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
387 if (Offset < 0) {
388 Offset = -Offset;
389 isSub = true;
390 }
391 }
392
393 if (NewOpc != Opcode)
394 MI.setDesc(TII.get(NewOpc));
395
396 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
397
398 // Attempt to fold address computation
399 // Common case: small offset, fits into instruction.
400 int ImmedOffset = Offset / Scale;
401 unsigned Mask = (1 << NumBits) - 1;
402 if ((unsigned)Offset <= Mask * Scale) {
403 // Replace the FrameIndex with fp/sp
404 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
405 if (isSub) {
406 if (AddrMode == ARMII::AddrMode5)
407 // FIXME: Not consistent.
408 ImmedOffset |= 1 << NumBits;
409 else
410 ImmedOffset = -ImmedOffset;
411 }
412 ImmOp.ChangeToImmediate(ImmedOffset);
413 return 0;
414 }
415
416 // Otherwise, offset doesn't fit. Pull in what we can to simplify
417 ImmedOffset = Offset & Mask;
418 if (isSub) {
419 if (AddrMode == ARMII::AddrMode5)
420 // FIXME: Not consistent.
421 ImmedOffset |= 1 << NumBits;
422 else
423 ImmedOffset = -ImmedOffset;
424 }
425 ImmOp.ChangeToImmediate(ImmedOffset);
426 Offset &= ~(Mask*Scale);
427 }
428
429 return (isSub) ? -Offset : Offset;
430 }
3030 // if there is not such an opcode.
3131 unsigned getUnindexedOpcode(unsigned Opc) const;
3232
33 // Return the opcode that implements 'Op', or 0 if no opcode
34 unsigned getOpcode(ARMII::Op Op) const;
35
3633 // Return true if the block does not fall through.
3734 bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
3835
5959 .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0);
6060 }
6161
62 static unsigned
63 negativeOffsetOpcode(unsigned opcode)
64 {
65 switch (opcode) {
66 case ARM::t2LDRi12: return ARM::t2LDRi8;
67 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
68 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
69 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
70 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
71 case ARM::t2STRi12: return ARM::t2STRi8;
72 case ARM::t2STRBi12: return ARM::t2STRBi8;
73 case ARM::t2STRHi12: return ARM::t2STRHi8;
74
75 case ARM::t2LDRi8:
76 case ARM::t2LDRHi8:
77 case ARM::t2LDRBi8:
78 case ARM::t2LDRSHi8:
79 case ARM::t2LDRSBi8:
80 case ARM::t2STRi8:
81 case ARM::t2STRBi8:
82 case ARM::t2STRHi8:
83 return opcode;
84
85 default:
86 break;
87 }
88
89 return 0;
90 }
91
92 static unsigned
93 positiveOffsetOpcode(unsigned opcode)
94 {
95 switch (opcode) {
96 case ARM::t2LDRi8: return ARM::t2LDRi12;
97 case ARM::t2LDRHi8: return ARM::t2LDRHi12;
98 case ARM::t2LDRBi8: return ARM::t2LDRBi12;
99 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
100 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
101 case ARM::t2STRi8: return ARM::t2STRi12;
102 case ARM::t2STRBi8: return ARM::t2STRBi12;
103 case ARM::t2STRHi8: return ARM::t2STRHi12;
104
105 case ARM::t2LDRi12:
106 case ARM::t2LDRHi12:
107 case ARM::t2LDRBi12:
108 case ARM::t2LDRSHi12:
109 case ARM::t2LDRSBi12:
110 case ARM::t2STRi12:
111 case ARM::t2STRBi12:
112 case ARM::t2STRHi12:
113 return opcode;
114
115 default:
116 break;
117 }
118
119 return 0;
120 }
121
122 static unsigned
123 immediateOffsetOpcode(unsigned opcode)
124 {
125 switch (opcode) {
126 case ARM::t2LDRs: return ARM::t2LDRi12;
127 case ARM::t2LDRHs: return ARM::t2LDRHi12;
128 case ARM::t2LDRBs: return ARM::t2LDRBi12;
129 case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
130 case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
131 case ARM::t2STRs: return ARM::t2STRi12;
132 case ARM::t2STRBs: return ARM::t2STRBi12;
133 case ARM::t2STRHs: return ARM::t2STRHi12;
134
135 case ARM::t2LDRi12:
136 case ARM::t2LDRHi12:
137 case ARM::t2LDRBi12:
138 case ARM::t2LDRSHi12:
139 case ARM::t2LDRSBi12:
140 case ARM::t2STRi12:
141 case ARM::t2STRBi12:
142 case ARM::t2STRHi12:
143 case ARM::t2LDRi8:
144 case ARM::t2LDRHi8:
145 case ARM::t2LDRBi8:
146 case ARM::t2LDRSHi8:
147 case ARM::t2LDRSBi8:
148 case ARM::t2STRi8:
149 case ARM::t2STRBi8:
150 case ARM::t2STRHi8:
151 return opcode;
152
153 default:
154 break;
155 }
156
157 return 0;
158 }
159
16062 bool Thumb2RegisterInfo::
16163 requiresRegisterScavenging(const MachineFunction &MF) const {
16264 return true;
16365 }
164
165 int Thumb2RegisterInfo::
166 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
167 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
168 unsigned FrameReg, int Offset) const
169 {
170 unsigned Opcode = MI.getOpcode();
171 const TargetInstrDesc &Desc = MI.getDesc();
172 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
173 bool isSub = false;
174
175 // Memory operands in inline assembly always use AddrModeT2_i12
176 if (Opcode == ARM::INLINEASM)
177 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
178
179 if (Opcode == ADDriOpc) {
180 Offset += MI.getOperand(FrameRegIdx+1).getImm();
181 if (Offset == 0) {
182 // Turn it into a move.
183 MI.setDesc(TII.get(MOVOpc));
184 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
185 MI.RemoveOperand(FrameRegIdx+1);
186 return 0;
187 } else if (Offset < 0) {
188 Offset = -Offset;
189 isSub = true;
190 MI.setDesc(TII.get(SUBriOpc));
191 }
192
193 // Common case: small offset, fits into instruction.
194 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
195 // Replace the FrameIndex with sp / fp
196 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
197 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
198 return 0;
199 }
200
201 // Otherwise, extract 8 adjacent bits from the immediate into this
202 // t2ADDri/t2SUBri.
203 unsigned RotAmt = CountLeadingZeros_32(Offset);
204 if (RotAmt > 24)
205 RotAmt = 24;
206 unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt);
207
208 // We will handle these bits from offset, clear them.
209 Offset &= ~ThisImmVal;
210
211 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
212 "Bit extraction didn't work?");
213 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
214 } else {
215 // AddrModeT2_so cannot handle any offset. If there is no offset
216 // register then we change to an immediate version.
217 if (AddrMode == ARMII::AddrModeT2_so) {
218 unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg();
219 if (OffsetReg != 0) {
220 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
221 return Offset;
222 }
223
224 MI.RemoveOperand(FrameRegIdx+1);
225 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
226 Opcode = immediateOffsetOpcode(Opcode);
227 AddrMode = ARMII::AddrModeT2_i12;
228 }
229
230 // Neon and FP address modes are handled by the base ARM version...
231 if ((AddrMode != ARMII::AddrModeT2_i8) &&
232 (AddrMode != ARMII::AddrModeT2_i12)) {
233 return ARMBaseRegisterInfo::rewriteFrameIndex(MI, FrameRegIdx,
234 ARM::t2MOVr, ARM::t2ADDri, ARM::t2SUBri, FrameReg, Offset);
235 }
236
237 unsigned NumBits = 0;
238 Offset += MI.getOperand(FrameRegIdx+1).getImm();
239
240 // i8 supports only negative, and i12 supports only positive, so
241 // based on Offset sign convert Opcode to the appropriate
242 // instruction
243 if (Offset < 0) {
244 Opcode = negativeOffsetOpcode(Opcode);
245 NumBits = 8;
246 isSub = true;
247 Offset = -Offset;
248 }
249 else {
250 Opcode = positiveOffsetOpcode(Opcode);
251 NumBits = 12;
252 }
253
254 if (Opcode) {
255 MI.setDesc(TII.get(Opcode));
256 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
257
258 // Attempt to fold address computation
259 // Common case: small offset, fits into instruction.
260 unsigned Mask = (1 << NumBits) - 1;
261 if ((unsigned)Offset <= Mask) {
262 // Replace the FrameIndex with fp/sp
263 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
264 ImmOp.ChangeToImmediate((isSub) ? -Offset : Offset);
265 return 0;
266 }
267
268 // Otherwise, offset doesn't fit. Pull in what we can to simplify
269 unsigned ImmedOffset = Offset & Mask;
270 ImmOp.ChangeToImmediate((isSub) ? -ImmedOffset : ImmedOffset);
271 Offset &= ~Mask;
272 }
273 }
274
275 return (isSub) ? -Offset : Offset;
276 }
3636 unsigned PredReg = 0) const;
3737
3838 bool requiresRegisterScavenging(const MachineFunction &MF) const;
39
40 // rewrite MI to access 'Offset' bytes from the FP. Return the offset that
41 // could not be handled directly in MI.
42 virtual int
43 rewriteFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
44 unsigned MOVOpc, unsigned ADDriOpc, unsigned SUBriOpc,
45 unsigned FrameReg, int Offset) const;
46
47 void eliminateFrameIndex(MachineBasicBlock::iterator II,
48 int SPAdj, RegScavenger *RS = NULL) const {
49 ARMBaseRegisterInfo::eliminateFrameIndexImpl(II, ARM::t2MOVr, ARM::t2ADDri,
50 ARM::t2SUBri, SPAdj, RS);
51 }
5239 };
5340 }
5441
0 ; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | FileCheck %s
1
2 define void @test1() {
3 ; CHECK: test1:
4 ; CHECK: sub.w sp, sp, #256
5 %tmp = alloca [ 64 x i32 ] , align 4
6 ret void
7 }
8
9 define void @test2() {
10 ; CHECK: test2:
11 ; CHECK: sub.w sp, sp, #4160
12 ; CHECK: sub.w sp, sp, #8
13 %tmp = alloca [ 4168 x i8 ] , align 4
14 ret void
15 }
16
17 define i32 @test3() {
18 ; CHECK: test3:
19 ; CHECK: sub.w sp, sp, #805306368
20 ; CHECK: sub.w sp, sp, #16
21 %retval = alloca i32, align 4
22 %tmp = alloca i32, align 4
23 %a = alloca [805306369 x i8], align 16
24 store i32 0, i32* %tmp
25 %tmp1 = load i32* %tmp
26 ret i32 %tmp1
27 }