llvm.org GIT mirror llvm / f602a25
Fix a bug handling frame references in ppc inline asm when the frame offset doesn't fit into 16 bits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43032 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 12 years ago
2 changed file(s) with 48 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
721721 MachineFrameInfo *MFI = MF.getFrameInfo();
722722
723723 // Find out which operand is the frame index.
724 unsigned i = 0;
725 while (!MI.getOperand(i).isFrameIndex()) {
726 ++i;
727 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
724 unsigned FIOperandNo = 0;
725 while (!MI.getOperand(FIOperandNo).isFrameIndex()) {
726 ++FIOperandNo;
727 assert(FIOperandNo != MI.getNumOperands() &&
728 "Instr doesn't have FrameIndex operand!");
728729 }
729730 // Take into account whether it's an add or mem instruction
730 unsigned OffIdx = (i == 2) ? 1 : 2;
731 unsigned OffsetOperandNo = (FIOperandNo == 2) ? 1 : 2;
731732 if (MI.getOpcode() == TargetInstrInfo::INLINEASM)
732 OffIdx = i-1;
733 OffsetOperandNo = FIOperandNo-1;
733734
734735 // Get the frame index.
735 int FrameIndex = MI.getOperand(i).getFrameIndex();
736 int FrameIndex = MI.getOperand(FIOperandNo).getFrameIndex();
736737
737738 // Get the frame pointer save index. Users of this index are primarily
738739 // DYNALLOC instructions.
749750 }
750751
751752 // Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP).
752 MI.getOperand(i).ChangeToRegister(hasFP(MF) ? PPC::R31 : PPC::R1, false);
753 MI.getOperand(FIOperandNo).ChangeToRegister(hasFP(MF) ? PPC::R31 : PPC::R1,
754 false);
753755
754756 // Figure out if the offset in the instruction is shifted right two bits. This
755757 // is true for instructions like "STD", which the machine implicitly adds two
766768
767769 // Now add the frame object offset to the offset from r1.
768770 int Offset = MFI->getObjectOffset(FrameIndex);
769
770771 if (!isIXAddr)
771 Offset += MI.getOperand(OffIdx).getImmedValue();
772 Offset += MI.getOperand(OffsetOperandNo).getImmedValue();
772773 else
773 Offset += MI.getOperand(OffIdx).getImmedValue() << 2;
774 Offset += MI.getOperand(OffsetOperandNo).getImmedValue() << 2;
774775
775776 // If we're not using a Frame Pointer that has been set to the value of the
776777 // SP before having the stack size subtracted from it, then add the stack size
777778 // to Offset to get the correct offset.
778779 Offset += MFI->getStackSize();
779780
780 if (!isInt16(Offset)) {
781 if (isInt16(Offset)) {
782 if (isIXAddr) {
783 assert((Offset & 3) == 0 && "Invalid frame offset!");
784 Offset >>= 2; // The actual encoded value has the low two bits zero.
785 }
786 MI.getOperand(OffsetOperandNo).ChangeToImmediate(Offset);
787 } else {
781788 // Insert a set of r0 with the full offset value before the ld, st, or add
782789 BuildMI(MBB, II, TII.get(PPC::LIS), PPC::R0).addImm(Offset >> 16);
783790 BuildMI(MBB, II, TII.get(PPC::ORI), PPC::R0).addReg(PPC::R0).addImm(Offset);
784791
785 // convert into indexed form of the instruction
792 // Convert into indexed form of the instruction
786793 // sth 0:rA, 1:imm 2:(rB) ==> sthx 0:rA, 2:rB, 1:r0
787794 // addi 0:rA 1:rB, 2, imm ==> add 0:rA, 1:rB, 2:r0
788 assert(ImmToIdxMap.count(OpC) &&
789 "No indexed form of load or store available!");
790 unsigned NewOpcode = ImmToIdxMap.find(OpC)->second;
791 MI.setInstrDescriptor(TII.get(NewOpcode));
792 MI.getOperand(1).ChangeToRegister(MI.getOperand(i).getReg(), false);
793 MI.getOperand(2).ChangeToRegister(PPC::R0, false);
794 } else {
795 if (isIXAddr) {
796 assert((Offset & 3) == 0 && "Invalid frame offset!");
797 Offset >>= 2; // The actual encoded value has the low two bits zero.
798 }
799 MI.getOperand(OffIdx).ChangeToImmediate(Offset);
795 unsigned OperandBase;
796 if (OpC != TargetInstrInfo::INLINEASM) {
797 assert(ImmToIdxMap.count(OpC) &&
798 "No indexed form of load or store available!");
799 unsigned NewOpcode = ImmToIdxMap.find(OpC)->second;
800 MI.setInstrDescriptor(TII.get(NewOpcode));
801 OperandBase = 1;
802 } else {
803 OperandBase = OffsetOperandNo;
804 }
805
806 unsigned StackReg = MI.getOperand(FIOperandNo).getReg();
807 MI.getOperand(OperandBase).ChangeToRegister(StackReg, false);
808 MI.getOperand(OperandBase+1).ChangeToRegister(PPC::R0, false);
800809 }
801810 }
802811
0 ; RUN: llvm-as < %s | llc -march=ppc32
1 ; rdar://5538377
2
3 %struct.disk_unsigned = type { i32 }
4 %struct._StorePageMax = type { %struct.disk_unsigned, %struct.disk_unsigned, [65536 x i8] }
5
6 define i32 @test() {
7 entry:
8 %data = alloca i32 ; [#uses=1]
9 %compressedPage = alloca %struct._StorePageMax ; <%struct._StorePageMax*> [#uses=0]
10 %tmp107 = call i32 asm "lwbrx $0, $2, $1", "=r,r,bO,*m"( i8* null, i32 0, i32* %data ) ; [#uses=0]
11 unreachable
12 }
13