[llvm-commits] [llvm] r76890 - in /llvm/trunk: lib/Target/ARM/ARMConstantIslandPass.cpp test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll
Evan Cheng
evan.cheng at apple.com
Thu Jul 23 11:27:48 PDT 2009
Author: evancheng
Date: Thu Jul 23 13:27:47 2009
New Revision: 76890
URL: http://llvm.org/viewvc/llvm-project?rev=76890&view=rev
Log:
Fix up ARM constant island pass for Thumb2.
Also fixed up code to fully use the SoImm field for ADR on ARM mode.
Added:
llvm/trunk/test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll
Modified:
llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
Modified: llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp?rev=76890&r1=76889&r2=76890&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp Thu Jul 23 13:27:47 2009
@@ -15,6 +15,7 @@
#define DEBUG_TYPE "arm-cp-islands"
#include "ARM.h"
+#include "ARMAddressingModes.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMInstrInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -72,8 +73,10 @@
MachineInstr *CPEMI;
unsigned MaxDisp;
bool NegOk;
- CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, bool neg)
- : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg) {}
+ bool IsSoImm;
+ CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
+ bool neg, bool soimm)
+ : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm) {}
};
/// CPUsers - Keep track of all of the machine instructions that use various
@@ -126,7 +129,7 @@
const TargetInstrInfo *TII;
ARMFunctionInfo *AFI;
bool isThumb;
- bool isThumb1Only;
+ bool isThumb1;
bool isThumb2;
public:
static char ID;
@@ -164,7 +167,7 @@
bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water,
CPUser &U);
bool OffsetIsInRange(unsigned UserOffset, unsigned TrialOffset,
- unsigned Disp, bool NegativeOK);
+ unsigned Disp, bool NegativeOK, bool IsSoImm = false);
bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
bool FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br);
bool FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br);
@@ -183,18 +186,20 @@
assert(BBOffsets.size() == BBSizes.size());
for (unsigned i = 1, e = BBOffsets.size(); i != e; ++i)
assert(BBOffsets[i-1]+BBSizes[i-1] == BBOffsets[i]);
- if (isThumb) {
- for (MachineFunction::iterator MBBI = Fn.begin(), E = Fn.end();
- MBBI != E; ++MBBI) {
- MachineBasicBlock *MBB = MBBI;
- if (!MBB->empty() &&
- MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY)
- assert((BBOffsets[MBB->getNumber()]%4 == 0 &&
- BBSizes[MBB->getNumber()]%4 == 0) ||
- (BBOffsets[MBB->getNumber()]%4 != 0 &&
- BBSizes[MBB->getNumber()]%4 != 0));
+ if (!isThumb)
+ return;
+#ifndef NDEBUG
+ for (MachineFunction::iterator MBBI = Fn.begin(), E = Fn.end();
+ MBBI != E; ++MBBI) {
+ MachineBasicBlock *MBB = MBBI;
+ if (!MBB->empty() &&
+ MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) {
+ unsigned MBBId = MBB->getNumber();
+ assert((BBOffsets[MBBId]%4 == 0 && BBSizes[MBBId]%4 == 0) ||
+ (BBOffsets[MBBId]%4 != 0 && BBSizes[MBBId]%4 != 0));
}
}
+#endif
}
/// print block size and offset information - debugging
@@ -217,7 +222,7 @@
TII = Fn.getTarget().getInstrInfo();
AFI = Fn.getInfo<ARMFunctionInfo>();
isThumb = AFI->isThumbFunction();
- isThumb1Only = AFI->isThumb1OnlyFunction();
+ isThumb1 = AFI->isThumb1OnlyFunction();
isThumb2 = AFI->isThumb2Function();
HasFarJump = false;
@@ -226,17 +231,19 @@
// the numbers agree with the position of the block in the function.
Fn.RenumberBlocks();
- /// Thumb1 functions containing constant pools get 2-byte alignment.
- /// This is so we can keep exact track of where the alignment padding goes.
- /// Set default.
- AFI->setAlign(isThumb1Only ? 1U : 2U);
+ // Thumb1 functions containing constant pools get 2-byte alignment.
+ // This is so we can keep exact track of where the alignment padding goes.
+
+ // Set default. Thumb1 function is 1-byte aligned, ARM and Thumb2 are 2-byte
+ // aligned.
+ AFI->setAlign(isThumb1 ? 1U : 2U);
// Perform the initial placement of the constant pool entries. To start with,
// we put them all at the end of the function.
std::vector<MachineInstr*> CPEMIs;
if (!MCP.isEmpty()) {
DoInitialPlacement(Fn, CPEMIs);
- if (isThumb1Only)
+ if (isThumb1)
AFI->setAlign(2U);
}
@@ -431,6 +438,9 @@
if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET)
PushPopMIs.push_back(I);
+ if (Opc == ARM::CONSTPOOL_ENTRY)
+ continue;
+
// Scan the instructions for constant pool operands.
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
if (I->getOperand(op).isCPI()) {
@@ -440,55 +450,52 @@
// Basic size info comes from the TSFlags field.
unsigned Bits = 0;
unsigned Scale = 1;
- unsigned TSFlags = I->getDesc().TSFlags;
bool NegOk = false;
- switch (TSFlags & ARMII::AddrModeMask) {
+ bool IsSoImm = false;
+
+ switch (Opc) {
default:
- // Constant pool entries can reach anything.
- if (I->getOpcode() == ARM::CONSTPOOL_ENTRY)
- continue;
- if (I->getOpcode() == ARM::tLEApcrel) {
- Bits = 8; // Taking the address of a CP entry.
- break;
- }
llvm_unreachable("Unknown addressing mode for CP reference!");
- case ARMII::AddrMode1: // AM1: 8 bits << 2 - FIXME: this is wrong?
- Bits = 8;
- Scale = 4; // Taking the address of a CP entry.
- NegOk = true;
break;
- case ARMII::AddrMode2:
- Bits = 12; // +-offset_12
+
+ // Taking the address of a CP entry.
+ case ARM::LEApcrel:
+ // This takes a SoImm, which is 8 bit immediate rotated. We'll
+ // pretend the maximum offset is 255 * 4. Since each instruction
+ // 4 byte wide, this is always correct. We'llc heck for other
+ // displacements that fits in a SoImm as well.
+ Bits = 8;
+ Scale = 4;
NegOk = true;
+ IsSoImm = true;
break;
- case ARMII::AddrMode3:
- Bits = 8; // +-offset_8
+ case ARM::t2LEApcrel:
+ Bits = 12;
NegOk = true;
break;
- // addrmode4 has no immediate offset.
- case ARMII::AddrMode5:
+ case ARM::tLEApcrel:
Bits = 8;
- Scale = 4; // +-(offset_8*4)
- NegOk = true;
+ Scale = 4;
break;
- // addrmode6 has no immediate offset.
- case ARMII::AddrModeT1_1:
- Bits = 5; // +offset_5
- break;
- case ARMII::AddrModeT1_2:
- Bits = 5;
- Scale = 2; // +(offset_5*2)
- break;
- case ARMII::AddrModeT1_4:
- Bits = 5;
- Scale = 4; // +(offset_5*4)
+
+ case ARM::LDR:
+ case ARM::LDRcp:
+ case ARM::t2LDRpci:
+ Bits = 12; // +-offset_12
+ NegOk = true;
break;
- case ARMII::AddrModeT1_s:
+
+ case ARM::tLDRpci:
+ case ARM::tLDRcp:
Bits = 8;
Scale = 4; // +(offset_8*4)
break;
- case ARMII::AddrModeT2_pc:
- Bits = 12; // +-offset_12
+
+ case ARM::FLDD:
+ case ARM::FLDS:
+ Bits = 8;
+ Scale = 4; // +-(offset_8*4)
+ NegOk = true;
break;
}
@@ -496,7 +503,7 @@
unsigned CPI = I->getOperand(op).getIndex();
MachineInstr *CPEMI = CPEMIs[CPI];
unsigned MaxOffs = ((1 << Bits)-1) * Scale;
- CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk));
+ CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk, IsSoImm));
// Increment corresponding CPEntry reference count.
CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
@@ -657,7 +664,7 @@
// We removed instructions from UserMBB, subtract that off from its size.
// Add 2 or 4 to the block to count the unconditional branch we added to it.
- unsigned delta = isThumb1Only ? 2 : 4;
+ unsigned delta = isThumb1 ? 2 : 4;
BBSizes[OrigBBI] -= NewBBSize - delta;
// ...and adjust BBOffsets for NewBB accordingly.
@@ -673,7 +680,8 @@
/// reference) is within MaxDisp of TrialOffset (a proposed location of a
/// constant pool entry).
bool ARMConstantIslands::OffsetIsInRange(unsigned UserOffset,
- unsigned TrialOffset, unsigned MaxDisp, bool NegativeOK) {
+ unsigned TrialOffset, unsigned MaxDisp,
+ bool NegativeOK, bool IsSoImm) {
// On Thumb offsets==2 mod 4 are rounded down by the hardware for
// purposes of the displacement computation; compensate for that here.
// Effectively, the valid range of displacements is 2 bytes smaller for such
@@ -686,10 +694,14 @@
if (UserOffset <= TrialOffset) {
// User before the Trial.
- if (TrialOffset-UserOffset <= MaxDisp)
+ if (TrialOffset - UserOffset <= MaxDisp)
+ return true;
+ if (IsSoImm && ARM_AM::getSOImmVal(TrialOffset - UserOffset) != -1)
return true;
} else if (NegativeOK) {
- if (UserOffset-TrialOffset <= MaxDisp)
+ if (UserOffset - TrialOffset <= MaxDisp)
+ return true;
+ if (IsSoImm && ARM_AM::getSOImmVal(~(TrialOffset - UserOffset)) != -1)
return true;
}
return false;
@@ -701,7 +713,6 @@
bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset,
MachineBasicBlock* Water, CPUser &U) {
unsigned MaxDisp = U.MaxDisp;
- MachineFunction::iterator I = next(MachineFunction::iterator(Water));
unsigned CPEOffset = BBOffsets[Water->getNumber()] +
BBSizes[Water->getNumber()];
@@ -711,7 +722,7 @@
if (CPEOffset < UserOffset)
UserOffset += U.CPEMI->getOperand(2).getImm();
- return OffsetIsInRange(UserOffset, CPEOffset, MaxDisp, U.NegOk);
+ return OffsetIsInRange(UserOffset, CPEOffset, MaxDisp, U.NegOk, U.IsSoImm);
}
/// CPEIsInRange - Returns true if the distance between specific MI and
@@ -753,52 +764,50 @@
void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB,
int delta) {
MachineFunction::iterator MBBI = BB; MBBI = next(MBBI);
- for(unsigned i=BB->getNumber()+1; i<BB->getParent()->getNumBlockIDs(); i++) {
+ for(unsigned i = BB->getNumber()+1, e = BB->getParent()->getNumBlockIDs();
+ i < e; ++i) {
BBOffsets[i] += delta;
// If some existing blocks have padding, adjust the padding as needed, a
// bit tricky. delta can be negative so don't use % on that.
- if (isThumb) {
- MachineBasicBlock *MBB = MBBI;
- if (!MBB->empty()) {
- // Constant pool entries require padding.
- if (MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) {
- unsigned oldOffset = BBOffsets[i] - delta;
- if (oldOffset%4==0 && BBOffsets[i]%4!=0) {
- // add new padding
- BBSizes[i] += 2;
- delta += 2;
- } else if (oldOffset%4!=0 && BBOffsets[i]%4==0) {
- // remove existing padding
- BBSizes[i] -=2;
- delta -= 2;
- }
+ if (!isThumb)
+ continue;
+ MachineBasicBlock *MBB = MBBI;
+ if (!MBB->empty()) {
+ // Constant pool entries require padding.
+ if (MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) {
+ unsigned oldOffset = BBOffsets[i] - delta;
+ if (oldOffset%4==0 && BBOffsets[i]%4!=0) {
+ // add new padding
+ BBSizes[i] += 2;
+ delta += 2;
+ } else if (oldOffset%4!=0 && BBOffsets[i]%4==0) {
+ // remove existing padding
+ BBSizes[i] -=2;
+ delta -= 2;
}
- // Thumb jump tables require padding. They should be at the end;
- // following unconditional branches are removed by AnalyzeBranch.
- MachineInstr *ThumbJTMI = NULL;
- if ((prior(MBB->end())->getOpcode() == ARM::tBR_JTr)
- || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTr)
- || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTm)
- || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTadd))
- ThumbJTMI = prior(MBB->end());
- if (ThumbJTMI) {
- unsigned newMIOffset = GetOffsetOf(ThumbJTMI);
- unsigned oldMIOffset = newMIOffset - delta;
- if (oldMIOffset%4 == 0 && newMIOffset%4 != 0) {
- // remove existing padding
- BBSizes[i] -= 2;
- delta -= 2;
- } else if (oldMIOffset%4 != 0 && newMIOffset%4 == 0) {
- // add new padding
- BBSizes[i] += 2;
- delta += 2;
- }
+ }
+ // Thumb1 jump tables require padding. They should be at the end;
+ // following unconditional branches are removed by AnalyzeBranch.
+ MachineInstr *ThumbJTMI = NULL;
+ if (prior(MBB->end())->getOpcode() == ARM::tBR_JTr)
+ ThumbJTMI = prior(MBB->end());
+ if (ThumbJTMI) {
+ unsigned newMIOffset = GetOffsetOf(ThumbJTMI);
+ unsigned oldMIOffset = newMIOffset - delta;
+ if (oldMIOffset%4 == 0 && newMIOffset%4 != 0) {
+ // remove existing padding
+ BBSizes[i] -= 2;
+ delta -= 2;
+ } else if (oldMIOffset%4 != 0 && newMIOffset%4 == 0) {
+ // add new padding
+ BBSizes[i] += 2;
+ delta += 2;
}
- if (delta==0)
- return;
}
- MBBI = next(MBBI);
+ if (delta==0)
+ return;
}
+ MBBI = next(MBBI);
}
}
@@ -900,22 +909,21 @@
/// we can place the CPE referenced from U so it's within range of U's MI.
/// Returns true if found, false if not. If it returns true, *NewMBB
/// is set to the WaterList entry.
-/// For ARM, we prefer the water that's farthest away. For Thumb, prefer
+/// For ARM, we prefer the water that's farthest away. For Thumb, prefer
/// water that will not introduce padding to water that will; within each
/// group, prefer the water that's farthest away.
-
bool ARMConstantIslands::LookForWater(CPUser &U, unsigned UserOffset,
MachineBasicBlock** NewMBB) {
std::vector<MachineBasicBlock*>::iterator IPThatWouldPad;
MachineBasicBlock* WaterBBThatWouldPad = NULL;
if (!WaterList.empty()) {
for (std::vector<MachineBasicBlock*>::iterator IP = prior(WaterList.end()),
- B = WaterList.begin();; --IP) {
+ B = WaterList.begin();; --IP) {
MachineBasicBlock* WaterBB = *IP;
if (WaterIsInRange(UserOffset, WaterBB, U)) {
+ unsigned WBBId = WaterBB->getNumber();
if (isThumb &&
- (BBOffsets[WaterBB->getNumber()] +
- BBSizes[WaterBB->getNumber()])%4 != 0) {
+ (BBOffsets[WBBId] + BBSizes[WBBId])%4 != 0) {
// This is valid Water, but would introduce padding. Remember
// it in case we don't find any Water that doesn't do this.
if (!WaterBBThatWouldPad) {
@@ -926,7 +934,7 @@
*NewMBB = AcceptWater(WaterBB, IP);
return true;
}
- }
+ }
if (IP == B)
break;
}
@@ -958,14 +966,14 @@
// If the use is at the end of the block, or the end of the block
// is within range, make new water there. (The addition below is
- // for the unconditional branch we will be adding: 4 bytes on ARM,
- // 2 on Thumb. Possible Thumb alignment padding is allowed for
+ // for the unconditional branch we will be adding: 4 bytes on ARM + Thumb2,
+ // 2 on Thumb1. Possible Thumb1 alignment padding is allowed for
// inside OffsetIsInRange.
// If the block ends in an unconditional branch already, it is water,
// and is known to be out of range, so we'll always be adding a branch.)
if (&UserMBB->back() == UserMI ||
- OffsetIsInRange(UserOffset, OffsetOfNextBlock + (isThumb ? 2: 4),
- U.MaxDisp, !isThumb)) {
+ OffsetIsInRange(UserOffset, OffsetOfNextBlock + (isThumb1 ? 2: 4),
+ U.MaxDisp, U.NegOk, U.IsSoImm)) {
DOUT << "Split at end of block\n";
if (&UserMBB->back() == UserMI)
assert(BBHasFallthrough(UserMBB) && "Expected a fallthrough BB!");
@@ -981,12 +989,12 @@
unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
ImmBranches.push_back(ImmBranch(&UserMBB->back(),
MaxDisp, false, UncondBr));
- int delta = isThumb ? 2 : 4;
+ int delta = isThumb1 ? 2 : 4;
BBSizes[UserMBB->getNumber()] += delta;
AdjustBBOffsetsAfter(UserMBB, delta);
} else {
// What a big block. Find a place within the block to split it.
- // This is a little tricky on Thumb since instructions are 2 bytes
+ // This is a little tricky on Thumb1 since instructions are 2 bytes
// and constant pool entries are 4 bytes: if instruction I references
// island CPE, and instruction I+1 references CPE', it will
// not work well to put CPE as far forward as possible, since then
@@ -999,7 +1007,7 @@
// if not, we back up the insertion point.
// The 4 in the following is for the unconditional branch we'll be
- // inserting (allows for long branch on Thumb). Alignment of the
+ // inserting (allows for long branch on Thumb1). Alignment of the
// island is handled inside OffsetIsInRange.
unsigned BaseInsertOffset = UserOffset + U.MaxDisp -4;
// This could point off the end of the block if we've already got
@@ -1008,7 +1016,7 @@
// conditional and a maximally long unconditional).
if (BaseInsertOffset >= BBOffsets[UserMBB->getNumber()+1])
BaseInsertOffset = BBOffsets[UserMBB->getNumber()+1] -
- (isThumb ? 6 : 8);
+ (isThumb1 ? 6 : 8);
unsigned EndInsertOffset = BaseInsertOffset +
CPEMI->getOperand(2).getImm();
MachineBasicBlock::iterator MI = UserMI;
@@ -1019,10 +1027,11 @@
Offset += TII->GetInstSizeInBytes(MI),
MI = next(MI)) {
if (CPUIndex < CPUsers.size() && CPUsers[CPUIndex].MI == MI) {
+ CPUser &U = CPUsers[CPUIndex];
if (!OffsetIsInRange(Offset, EndInsertOffset,
- CPUsers[CPUIndex].MaxDisp, !isThumb)) {
- BaseInsertOffset -= (isThumb ? 2 : 4);
- EndInsertOffset -= (isThumb ? 2 : 4);
+ U.MaxDisp, U.NegOk, U.IsSoImm)) {
+ BaseInsertOffset -= (isThumb1 ? 2 : 4);
+ EndInsertOffset -= (isThumb1 ? 2 : 4);
}
// This is overly conservative, as we don't account for CPEMIs
// being reused within the block, but it doesn't matter much.
@@ -1051,11 +1060,6 @@
// hardware keeps in the PC (2 insns ahead of the reference).
unsigned UserOffset = GetOffsetOf(UserMI) + (isThumb ? 4 : 8);
- // Special case: tLEApcrel are two instructions MI's. The actual user is the
- // second instruction.
- if (UserMI->getOpcode() == ARM::tLEApcrel)
- UserOffset += 2;
-
// See if the current entry is within range, or there is a clone of it
// in range.
int result = LookForExistingCPEntry(U, UserOffset);
@@ -1123,7 +1127,7 @@
BBSizes[CPEBB->getNumber()] -= Size;
// All succeeding offsets have the current size value added in, fix this.
if (CPEBB->empty()) {
- // In thumb mode, the size of island may be padded by two to compensate for
+ // In thumb1 mode, the size of island may be padded by two to compensate for
// the alignment requirement. Then it will now be 2 when the block is
// empty, so fix this.
// All succeeding offsets have the current size value added in, fix this.
@@ -1205,7 +1209,7 @@
ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br) {
MachineInstr *MI = Br.MI;
MachineBasicBlock *MBB = MI->getParent();
- assert(isThumb && !isThumb2 && "Expected a Thumb-1 function!");
+ assert(isThumb && !isThumb2 && "Expected a Thumb1 function!");
// Use BL to implement far jump.
Br.MaxDisp = (1 << 21) * 2;
Added: llvm/trunk/test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll?rev=76890&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll (added)
+++ llvm/trunk/test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll Thu Jul 23 13:27:47 2009
@@ -0,0 +1,22 @@
+; RUN: llvm-as < %s | llc -mtriple=thumbv7-apple-darwin9 -mattr=+vfp2,+thumb2
+; rdar://7083961
+
+define arm_apcscc i32 @value(i64 %b1, i64 %b2) nounwind readonly {
+entry:
+ %0 = icmp eq i32 undef, 0 ; <i1> [#uses=1]
+ %mod.0.ph.ph = select i1 %0, float -1.000000e+00, float 1.000000e+00 ; <float> [#uses=1]
+ br label %bb7
+
+bb7: ; preds = %bb7, %entry
+ br i1 undef, label %bb86.preheader, label %bb7
+
+bb86.preheader: ; preds = %bb7
+ %1 = fmul float %mod.0.ph.ph, 5.000000e+00 ; <float> [#uses=0]
+ br label %bb79
+
+bb79: ; preds = %bb79, %bb86.preheader
+ br i1 undef, label %bb119, label %bb79
+
+bb119: ; preds = %bb79
+ ret i32 undef
+}
More information about the llvm-commits
mailing list