Update LLVM to r103052.
This commit is contained in:
parent
d7f7719e5e
commit
59161dfae3
@ -632,22 +632,22 @@ Stop.
|
||||
<p>Use commands like this:</p>
|
||||
|
||||
<ol>
|
||||
<li><p>Compile your program as normal with llvm-g++:</p>
|
||||
<li><p>Compile your program with llvm-g++:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
% llvm-g++ x.cpp -o program
|
||||
% llvm-g++ -emit-llvm x.cpp -o program.bc -c
|
||||
</pre>
|
||||
|
||||
<p>or:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
% llvm-g++ a.cpp -c
|
||||
% llvm-g++ b.cpp -c
|
||||
% llvm-g++ a.o b.o -o program
|
||||
% llvm-g++ a.cpp -c -emit-llvm
|
||||
% llvm-g++ b.cpp -c -emit-llvm
|
||||
% llvm-ld a.o b.o -o program
|
||||
</pre>
|
||||
|
||||
<p>With llvm-gcc3, this will generate program and program.bc. The .bc
|
||||
file is the LLVM version of the program all linked together.</p></li>
|
||||
<p>This will generate program and program.bc. The .bc
|
||||
file is the LLVM version of the program all linked together.</p></li>
|
||||
|
||||
<li><p>Convert the LLVM code to C code, using the LLC tool with the C
|
||||
backend:</p>
|
||||
@ -659,7 +659,7 @@ Stop.
|
||||
<li><p>Finally, compile the C file:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
% cc x.c
|
||||
% cc x.c -lstdc++
|
||||
</pre></li>
|
||||
|
||||
</ol>
|
||||
@ -931,7 +931,7 @@ F.i:
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-02-26 00:41:41 +0100 (Fri, 26 Feb 2010) $
|
||||
Last modified: $Date: 2010-05-04 20:16:00 +0200 (Tue, 04 May 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -262,6 +262,23 @@ static void printRegName(unsigned reg, const TargetRegisterInfo* tri_) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
bool MultipleDefsByMI(const MachineInstr &MI, unsigned MOIdx) {
|
||||
unsigned Reg = MI.getOperand(MOIdx).getReg();
|
||||
for (unsigned i = MOIdx+1, e = MI.getNumOperands(); i < e; ++i) {
|
||||
const MachineOperand &MO = MI.getOperand(i);
|
||||
if (!MO.isReg())
|
||||
continue;
|
||||
if (MO.getReg() == Reg && MO.isDef()) {
|
||||
assert(MI.getOperand(MOIdx).getSubReg() != MO.getSubReg() &&
|
||||
MI.getOperand(MOIdx).getSubReg() &&
|
||||
MO.getSubReg());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
|
||||
MachineBasicBlock::iterator mi,
|
||||
SlotIndex MIIdx,
|
||||
@ -372,6 +389,13 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
|
||||
}
|
||||
|
||||
} else {
|
||||
if (MultipleDefsByMI(*mi, MOIdx))
|
||||
// Mutple defs of the same virtual register by the same instruction. e.g.
|
||||
// %reg1031:5<def>, %reg1031:6<def> = VLD1q16 %reg1024<kill>, ...
|
||||
// This is likely due to elimination of REG_SEQUENCE instructions. Return
|
||||
// here since there is nothing to do.
|
||||
return;
|
||||
|
||||
// If this is the second time we see a virtual register definition, it
|
||||
// must be due to phi elimination or two addr elimination. If this is
|
||||
// the result of two address elimination, then the vreg is one of the
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
using namespace llvm;
|
||||
@ -52,22 +53,22 @@ void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) {
|
||||
MRI = &Fn.getRegInfo();
|
||||
bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &MF) {
|
||||
MRI = &MF.getRegInfo();
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
// Split critical edges to help the coalescer
|
||||
if (LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>())
|
||||
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
||||
Changed |= SplitPHIEdges(Fn, *I, *LV);
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
|
||||
Changed |= SplitPHIEdges(MF, *I, *LV);
|
||||
|
||||
// Populate VRegPHIUseCount
|
||||
analyzePHINodes(Fn);
|
||||
analyzePHINodes(MF);
|
||||
|
||||
// Eliminate PHI instructions by inserting copies into predecessor blocks.
|
||||
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
||||
Changed |= EliminatePHINodes(Fn, *I);
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
|
||||
Changed |= EliminatePHINodes(MF, *I);
|
||||
|
||||
// Remove dead IMPLICIT_DEF instructions.
|
||||
for (SmallPtrSet<MachineInstr*, 4>::iterator I = ImpDefs.begin(),
|
||||
@ -81,11 +82,16 @@ bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) {
|
||||
// Clean up the lowered PHI instructions.
|
||||
for (LoweredPHIMap::iterator I = LoweredPHIs.begin(), E = LoweredPHIs.end();
|
||||
I != E; ++I)
|
||||
Fn.DeleteMachineInstr(I->first);
|
||||
MF.DeleteMachineInstr(I->first);
|
||||
|
||||
LoweredPHIs.clear();
|
||||
ImpDefs.clear();
|
||||
VRegPHIUseCount.clear();
|
||||
|
||||
// Eliminate REG_SEQUENCE instructions. Their whole purpose was to preseve
|
||||
// SSA form.
|
||||
Changed |= EliminateRegSequences(MF);
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
@ -364,8 +370,8 @@ void llvm::PHIElimination::LowerAtomicPHINode(
|
||||
/// used in a PHI node. We map that to the BB the vreg is coming from. This is
|
||||
/// used later to determine when the vreg is killed in the BB.
|
||||
///
|
||||
void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) {
|
||||
for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end();
|
||||
void llvm::PHIElimination::analyzePHINodes(const MachineFunction& MF) {
|
||||
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
||||
I != E; ++I)
|
||||
for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end();
|
||||
BBI != BBE && BBI->isPHI(); ++BBI)
|
||||
@ -443,3 +449,58 @@ MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A,
|
||||
|
||||
return NMBB;
|
||||
}
|
||||
|
||||
static void UpdateRegSequenceSrcs(unsigned SrcReg,
|
||||
unsigned DstReg, unsigned SrcIdx,
|
||||
MachineRegisterInfo *MRI) {
|
||||
for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg),
|
||||
UE = MRI->reg_end(); RI != UE; ) {
|
||||
MachineOperand &MO = RI.getOperand();
|
||||
++RI;
|
||||
MO.setReg(DstReg);
|
||||
MO.setSubReg(SrcIdx);
|
||||
}
|
||||
}
|
||||
|
||||
/// EliminateRegSequences - Eliminate REG_SEQUENCE instructions as second part
|
||||
/// of de-ssa process. This replaces sources of REG_SEQUENCE as sub-register
|
||||
/// references of the register defined by REG_SEQUENCE. e.g.
|
||||
///
|
||||
/// %reg1029<def>, %reg1030<def> = VLD1q16 %reg1024<kill>, ...
|
||||
/// %reg1031<def> = REG_SEQUENCE %reg1029<kill>, 5, %reg1030<kill>, 6
|
||||
/// =>
|
||||
/// %reg1031:5<def>, %reg1031:6<def> = VLD1q16 %reg1024<kill>, ...
|
||||
bool PHIElimination::EliminateRegSequences(MachineFunction &MF) {
|
||||
bool Changed = false;
|
||||
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
|
||||
for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
|
||||
BBI != BBE; ) {
|
||||
MachineInstr &MI = *BBI;
|
||||
++BBI;
|
||||
if (MI.getOpcode() != TargetOpcode::REG_SEQUENCE)
|
||||
continue;
|
||||
unsigned DstReg = MI.getOperand(0).getReg();
|
||||
if (MI.getOperand(0).getSubReg() ||
|
||||
TargetRegisterInfo::isPhysicalRegister(DstReg) ||
|
||||
!(MI.getNumOperands() & 1)) {
|
||||
DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << MI);
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
for (unsigned i = 1, e = MI.getNumOperands(); i < e; i += 2) {
|
||||
unsigned SrcReg = MI.getOperand(i).getReg();
|
||||
if (MI.getOperand(i).getSubReg() ||
|
||||
TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
|
||||
DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << MI);
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
unsigned SrcIdx = MI.getOperand(i+1).getImm();
|
||||
UpdateRegSequenceSrcs(SrcReg, DstReg, SrcIdx, MRI);
|
||||
}
|
||||
|
||||
MI.eraseFromParent();
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ namespace llvm {
|
||||
return I;
|
||||
}
|
||||
|
||||
bool EliminateRegSequences(MachineFunction &MF);
|
||||
|
||||
typedef std::pair<unsigned, unsigned> BBVRegPair;
|
||||
typedef DenseMap<BBVRegPair, unsigned> VRegPHIUse;
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -34,6 +35,10 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool>
|
||||
UseRegSeq("neon-reg-sequence", cl::Hidden,
|
||||
cl::desc("Use reg_sequence to model ld / st of multiple neon regs"));
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// ARMDAGToDAGISel - ARM specific code to select ARM machine
|
||||
/// instructions for SelectionDAG operations.
|
||||
@ -939,10 +944,14 @@ SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) {
|
||||
/// form a quad register.
|
||||
SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) {
|
||||
DebugLoc dl = V0.getNode()->getDebugLoc();
|
||||
SDValue Undef =
|
||||
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
|
||||
SDValue SubReg0 = CurDAG->getTargetConstant(ARM::DSUBREG_0, MVT::i32);
|
||||
SDValue SubReg1 = CurDAG->getTargetConstant(ARM::DSUBREG_1, MVT::i32);
|
||||
if (UseRegSeq) {
|
||||
const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 };
|
||||
return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4);
|
||||
}
|
||||
SDValue Undef =
|
||||
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0);
|
||||
SDNode *Pair = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
|
||||
VT, Undef, V0, SubReg0);
|
||||
return CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
|
||||
|
@ -12,12 +12,14 @@
|
||||
#include "ARMInstrInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class NEONPreAllocPass : public MachineFunctionPass {
|
||||
const TargetInstrInfo *TII;
|
||||
MachineRegisterInfo *MRI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
@ -30,6 +32,8 @@ namespace {
|
||||
}
|
||||
|
||||
private:
|
||||
bool FormsRegSequence(MachineInstr *MI,
|
||||
unsigned FirstOpnd, unsigned NumRegs);
|
||||
bool PreAllocNEONRegisters(MachineBasicBlock &MBB);
|
||||
};
|
||||
|
||||
@ -334,6 +338,27 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NEONPreAllocPass::FormsRegSequence(MachineInstr *MI,
|
||||
unsigned FirstOpnd, unsigned NumRegs) {
|
||||
MachineInstr *RegSeq = 0;
|
||||
for (unsigned R = 0; R < NumRegs; ++R) {
|
||||
MachineOperand &MO = MI->getOperand(FirstOpnd + R);
|
||||
assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand");
|
||||
unsigned VirtReg = MO.getReg();
|
||||
assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
|
||||
"expected a virtual register");
|
||||
if (!MRI->hasOneNonDBGUse(VirtReg))
|
||||
return false;
|
||||
MachineInstr *UseMI = &*MRI->use_nodbg_begin(VirtReg);
|
||||
if (UseMI->getOpcode() != TargetOpcode::REG_SEQUENCE)
|
||||
return false;
|
||||
if (RegSeq && RegSeq != UseMI)
|
||||
return false;
|
||||
RegSeq = UseMI;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
|
||||
bool Modified = false;
|
||||
|
||||
@ -343,6 +368,8 @@ bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
|
||||
unsigned FirstOpnd, NumRegs, Offset, Stride;
|
||||
if (!isNEONMultiRegOp(MI->getOpcode(), FirstOpnd, NumRegs, Offset, Stride))
|
||||
continue;
|
||||
if (FormsRegSequence(MI, FirstOpnd, NumRegs))
|
||||
continue;
|
||||
|
||||
MachineBasicBlock::iterator NextI = llvm::next(MBBI);
|
||||
for (unsigned R = 0; R < NumRegs; ++R) {
|
||||
@ -382,6 +409,7 @@ bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
|
||||
|
||||
bool NEONPreAllocPass::runOnMachineFunction(MachineFunction &MF) {
|
||||
TII = MF.getTarget().getInstrInfo();
|
||||
MRI = &MF.getRegInfo();
|
||||
|
||||
bool Modified = false;
|
||||
for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
|
||||
|
@ -941,13 +941,21 @@ SPUDAGToDAGISel::Select(SDNode *N) {
|
||||
&& ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0
|
||||
&& RN->getReg() != SPU::R1))) {
|
||||
NewOpc = SPU::Ar32;
|
||||
Ops[1] = Op1;
|
||||
if (Op1.getOpcode() == ISD::Constant) {
|
||||
ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
|
||||
Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT);
|
||||
NewOpc = (isI32IntS10Immediate(CN) ? SPU::AIr32 : SPU::Ar32);
|
||||
if (isInt<10>(CN->getSExtValue())) {
|
||||
NewOpc = SPU::AIr32;
|
||||
Ops[1] = Op1;
|
||||
} else {
|
||||
Ops[1] = SDValue(CurDAG->getMachineNode(SPU::ILr32, dl,
|
||||
N->getValueType(0),
|
||||
Op1),
|
||||
0);
|
||||
}
|
||||
}
|
||||
Ops[0] = Op0;
|
||||
Ops[1] = Op1;
|
||||
n_ops = 2;
|
||||
}
|
||||
}
|
||||
|
@ -51,11 +51,14 @@ class X86ATTAsmParser : public TargetAsmParser {
|
||||
void InstructionCleanup(MCInst &Inst);
|
||||
|
||||
/// @name Auto-generated Match Functions
|
||||
/// {
|
||||
/// {
|
||||
|
||||
bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
MCInst &Inst);
|
||||
|
||||
bool MatchInstructionImpl(
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
|
||||
|
||||
/// }
|
||||
|
||||
public:
|
||||
@ -132,7 +135,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
|
||||
X86Operand(KindTy K, SMLoc Start, SMLoc End)
|
||||
: Kind(K), StartLoc(Start), EndLoc(End) {}
|
||||
|
||||
|
||||
/// getStartLoc - Get the location of the first token of this operand.
|
||||
SMLoc getStartLoc() const { return StartLoc; }
|
||||
/// getEndLoc - Get the location of the last token of this operand.
|
||||
@ -142,6 +145,11 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
assert(Kind == Token && "Invalid access!");
|
||||
return StringRef(Tok.Data, Tok.Length);
|
||||
}
|
||||
void setTokenValue(StringRef Value) {
|
||||
assert(Kind == Token && "Invalid access!");
|
||||
Tok.Data = Value.data();
|
||||
Tok.Length = Value.size();
|
||||
}
|
||||
|
||||
unsigned getReg() const {
|
||||
assert(Kind == Register && "Invalid access!");
|
||||
@ -632,6 +640,54 @@ void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
|
||||
&Operands,
|
||||
MCInst &Inst) {
|
||||
// First, try a direct match.
|
||||
if (!MatchInstructionImpl(Operands, Inst))
|
||||
return false;
|
||||
|
||||
// Ignore anything which is obviously not a suffix match.
|
||||
if (Operands.size() == 0)
|
||||
return true;
|
||||
X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
|
||||
if (!Op->isToken() || Op->getToken().size() > 15)
|
||||
return true;
|
||||
|
||||
// FIXME: Ideally, we would only attempt suffix matches for things which are
|
||||
// valid prefixes, and we could just infer the right unambiguous
|
||||
// type. However, that requires substantially more matcher support than the
|
||||
// following hack.
|
||||
|
||||
// Change the operand to point to a temporary token.
|
||||
char Tmp[16];
|
||||
StringRef Base = Op->getToken();
|
||||
memcpy(Tmp, Base.data(), Base.size());
|
||||
Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
|
||||
|
||||
// Check for the various suffix matches.
|
||||
Tmp[Base.size()] = 'b';
|
||||
bool MatchB = MatchInstructionImpl(Operands, Inst);
|
||||
Tmp[Base.size()] = 'w';
|
||||
bool MatchW = MatchInstructionImpl(Operands, Inst);
|
||||
Tmp[Base.size()] = 'l';
|
||||
bool MatchL = MatchInstructionImpl(Operands, Inst);
|
||||
|
||||
// Restore the old token.
|
||||
Op->setTokenValue(Base);
|
||||
|
||||
// If exactly one matched, then we treat that as a successful match (and the
|
||||
// instruction will already have been filled in correctly, since the failing
|
||||
// matches won't have modified it).
|
||||
if (MatchB + MatchW + MatchL == 2)
|
||||
return false;
|
||||
|
||||
// Otherwise, the match failed.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void LLVMInitializeX86AsmLexer();
|
||||
|
||||
// Force static initialization.
|
||||
|
@ -179,8 +179,9 @@ include "X86CallingConv.td"
|
||||
|
||||
// Currently the X86 assembly parser only supports ATT syntax.
|
||||
def ATTAsmParser : AsmParser {
|
||||
string AsmParserClassName = "ATTAsmParser";
|
||||
string AsmParserInstCleanup = "InstructionCleanup";
|
||||
string AsmParserClassName = "ATTAsmParser";
|
||||
string AsmParserInstCleanup = "InstructionCleanup";
|
||||
string MatchInstructionName = "MatchInstructionImpl";
|
||||
int Variant = 0;
|
||||
|
||||
// Discard comments in assembly strings.
|
||||
|
@ -1584,7 +1584,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
|
||||
for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i)
|
||||
FullyAvailableBlocks[UnavailableBlocks[i]] = false;
|
||||
|
||||
bool NeedToSplitEdges = false;
|
||||
SmallVector<std::pair<TerminatorInst*, unsigned>, 4> NeedToSplit;
|
||||
for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB);
|
||||
PI != E; ++PI) {
|
||||
BasicBlock *Pred = *PI;
|
||||
@ -1600,12 +1600,13 @@ bool GVN::processNonLocalLoad(LoadInst *LI,
|
||||
return false;
|
||||
}
|
||||
unsigned SuccNum = GetSuccessorNumber(Pred, LoadBB);
|
||||
toSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum));
|
||||
NeedToSplitEdges = true;
|
||||
NeedToSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum));
|
||||
}
|
||||
}
|
||||
if (NeedToSplitEdges)
|
||||
if (!NeedToSplit.empty()) {
|
||||
toSplit.append(NeedToSplit.size(), NeedToSplit.front());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decide whether PRE is profitable for this load.
|
||||
unsigned NumUnavailablePreds = PredLoads.size();
|
||||
|
@ -115,14 +115,17 @@ MDNode::~MDNode() {
|
||||
}
|
||||
|
||||
static const Function *getFunctionForValue(Value *V) {
|
||||
assert(!isa<MDNode>(V) && "does not iterate over metadata operands");
|
||||
if (!V) return NULL;
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
return I->getParent()->getParent();
|
||||
if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
|
||||
return BB->getParent();
|
||||
if (Instruction *I = dyn_cast<Instruction>(V)) {
|
||||
BasicBlock *BB = I->getParent();
|
||||
return BB ? BB->getParent() : 0;
|
||||
}
|
||||
if (Argument *A = dyn_cast<Argument>(V))
|
||||
return A->getParent();
|
||||
if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
|
||||
return BB->getParent();
|
||||
if (MDNode *MD = dyn_cast<MDNode>(V))
|
||||
return MD->getFunction();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -156,17 +159,9 @@ const Function *MDNode::getFunction() const {
|
||||
return assertLocalFunction(this);
|
||||
#endif
|
||||
if (!isFunctionLocal()) return NULL;
|
||||
|
||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
|
||||
if (Value *V = getOperand(i)) {
|
||||
if (MDNode *MD = dyn_cast<MDNode>(V)) {
|
||||
if (const Function *F = MD->getFunction())
|
||||
return F;
|
||||
} else {
|
||||
return getFunctionForValue(V);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
|
||||
if (const Function *F = getFunctionForValue(getOperand(i)))
|
||||
return F;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -272,8 +267,19 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
|
||||
// with an instruction or some other function-local object. If this is a
|
||||
// non-function-local MDNode, it can't point to a function-local object.
|
||||
// Handle this case by implicitly dropping the MDNode reference to null.
|
||||
if (!isFunctionLocal() && To && isFunctionLocalValue(To))
|
||||
To = 0;
|
||||
// Likewise if the MDNode is function-local but for a different function.
|
||||
if (To && isFunctionLocalValue(To)) {
|
||||
if (!isFunctionLocal())
|
||||
To = 0;
|
||||
else {
|
||||
const Function *F = getFunction();
|
||||
const Function *FV = getFunctionForValue(To);
|
||||
// Metadata can be function-local without having an associated function.
|
||||
// So only consider functions to have changed if non-null.
|
||||
if (F && FV && F != FV)
|
||||
To = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (From == To)
|
||||
return;
|
||||
|
13
test/CodeGen/CellSPU/storestruct.ll
Normal file
13
test/CodeGen/CellSPU/storestruct.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; RUN: llc < %s -march=cellspu | FileCheck %s
|
||||
|
||||
%0 = type {i32, i32}
|
||||
@buffer = global [ 72 x %0 ] zeroinitializer
|
||||
|
||||
define void@test( ) {
|
||||
; Check that there is no illegal "a rt, ra, imm" instruction
|
||||
; CHECK-NOT: a {{\$., \$., 5..}}
|
||||
; CHECK: a {{\$., \$., \$.}}
|
||||
store %0 {i32 1, i32 2} ,
|
||||
%0* getelementptr ([72 x %0]* @buffer, i32 0, i32 71)
|
||||
ret void
|
||||
}
|
6
test/MC/AsmParser/X86/x86_64-suffix-matching.s
Normal file
6
test/MC/AsmParser/X86/x86_64-suffix-matching.s
Normal file
@ -0,0 +1,6 @@
|
||||
// RUN: llvm-mc -triple x86_64 -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: addl $0, %eax
|
||||
add $0, %eax
|
||||
// CHECK: addb $255, %al
|
||||
add $0xFF, %al
|
@ -1,7 +1,8 @@
|
||||
; RUN: opt -S -globalopt < %s | FileCheck %s
|
||||
|
||||
; PR6112 - When globalopt does RAUW(@G, %G), the metadata reference should drop
|
||||
; to null.
|
||||
; to null. Function local metadata that references @G from a different function
|
||||
; to that containing %G should likewise drop to null.
|
||||
@G = internal global i8** null
|
||||
|
||||
define i32 @main(i32 %argc, i8** %argv) {
|
||||
@ -11,9 +12,15 @@ define i32 @main(i32 %argc, i8** %argv) {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define void @foo(i32 %x) {
|
||||
call void @llvm.foo(metadata !{i8*** @G, i32 %x})
|
||||
; CHECK: call void @llvm.foo(metadata !{null, i32 %x})
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.foo(metadata) nounwind readnone
|
||||
|
||||
!named = !{!0}
|
||||
|
||||
; CHECK: !0 = metadata !{null}
|
||||
!0 = metadata !{i8*** @G}
|
||||
|
||||
|
||||
; CHECK: !0 = metadata !{null}
|
||||
|
@ -17,11 +17,108 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/VectorExtras.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Diagnostic category computation code.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class DiagGroupParentMap {
|
||||
std::map<const Record*, std::vector<Record*> > Mapping;
|
||||
public:
|
||||
DiagGroupParentMap() {
|
||||
std::vector<Record*> DiagGroups
|
||||
= Records.getAllDerivedDefinitions("DiagGroup");
|
||||
for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
|
||||
std::vector<Record*> SubGroups =
|
||||
DiagGroups[i]->getValueAsListOfDefs("SubGroups");
|
||||
for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
|
||||
Mapping[SubGroups[j]].push_back(DiagGroups[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<Record*> &getParents(const Record *Group) {
|
||||
return Mapping[Group];
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
|
||||
static std::string
|
||||
getCategoryFromDiagGroup(const Record *Group,
|
||||
DiagGroupParentMap &DiagGroupParents) {
|
||||
// If the DiagGroup has a category, return it.
|
||||
std::string CatName = Group->getValueAsString("CategoryName");
|
||||
if (!CatName.empty()) return CatName;
|
||||
|
||||
// The diag group may the subgroup of one or more other diagnostic groups,
|
||||
// check these for a category as well.
|
||||
const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
|
||||
for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
|
||||
CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
|
||||
if (!CatName.empty()) return CatName;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// getDiagnosticCategory - Return the category that the specified diagnostic
|
||||
/// lives in.
|
||||
static std::string getDiagnosticCategory(const Record *R,
|
||||
DiagGroupParentMap &DiagGroupParents) {
|
||||
// If the diagnostic itself has a category, get it.
|
||||
std::string CatName = R->getValueAsString("CategoryName");
|
||||
if (!CatName.empty()) return CatName;
|
||||
|
||||
DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"));
|
||||
if (Group == 0) return "";
|
||||
|
||||
// Check the diagnostic's diag group for a category.
|
||||
return getCategoryFromDiagGroup(Group->getDef(), DiagGroupParents);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class DiagCategoryIDMap {
|
||||
StringMap<unsigned> CategoryIDs;
|
||||
std::vector<std::string> CategoryStrings;
|
||||
public:
|
||||
DiagCategoryIDMap() {
|
||||
DiagGroupParentMap ParentInfo;
|
||||
|
||||
// The zero'th category is "".
|
||||
CategoryStrings.push_back("");
|
||||
CategoryIDs[""] = 0;
|
||||
|
||||
std::vector<Record*> Diags =
|
||||
Records.getAllDerivedDefinitions("Diagnostic");
|
||||
for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
|
||||
std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
|
||||
if (Category.empty()) continue; // Skip diags with no category.
|
||||
|
||||
unsigned &ID = CategoryIDs[Category];
|
||||
if (ID != 0) continue; // Already seen.
|
||||
|
||||
ID = CategoryStrings.size();
|
||||
CategoryStrings.push_back(Category);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned getID(StringRef CategoryString) {
|
||||
return CategoryIDs[CategoryString];
|
||||
}
|
||||
|
||||
typedef std::vector<std::string>::iterator iterator;
|
||||
iterator begin() { return CategoryStrings.begin(); }
|
||||
iterator end() { return CategoryStrings.end(); }
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Warning Tables (.inc file) generation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -40,6 +137,9 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
|
||||
const std::vector<Record*> &Diags =
|
||||
Records.getAllDerivedDefinitions("Diagnostic");
|
||||
|
||||
DiagCategoryIDMap CategoryIDs;
|
||||
DiagGroupParentMap DGParentMap;
|
||||
|
||||
for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
|
||||
const Record &R = *Diags[i];
|
||||
// Filter by component.
|
||||
@ -67,6 +167,9 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
|
||||
OS << ", true";
|
||||
else
|
||||
OS << ", false";
|
||||
|
||||
// Category number.
|
||||
OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
|
||||
OS << ")\n";
|
||||
}
|
||||
}
|
||||
@ -82,6 +185,9 @@ struct GroupInfo {
|
||||
};
|
||||
|
||||
void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
|
||||
// Compute a mapping from a DiagGroup to all of its parents.
|
||||
DiagGroupParentMap DGParentMap;
|
||||
|
||||
// Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
|
||||
// groups to diags in the group.
|
||||
std::map<std::string, GroupInfo> DiagsInGroup;
|
||||
@ -98,9 +204,10 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
|
||||
|
||||
// Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
|
||||
// groups (these are warnings that GCC supports that clang never produces).
|
||||
Diags = Records.getAllDerivedDefinitions("DiagGroup");
|
||||
for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
|
||||
Record *Group = Diags[i];
|
||||
std::vector<Record*> DiagGroups
|
||||
= Records.getAllDerivedDefinitions("DiagGroup");
|
||||
for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
|
||||
Record *Group = DiagGroups[i];
|
||||
GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
|
||||
|
||||
std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
|
||||
@ -167,4 +274,12 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
|
||||
OS << " },\n";
|
||||
}
|
||||
OS << "#endif // GET_DIAG_TABLE\n\n";
|
||||
|
||||
// Emit the category table next.
|
||||
DiagCategoryIDMap CategoriesByID;
|
||||
OS << "\n#ifdef GET_CATEGORY_TABLE\n";
|
||||
for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
|
||||
E = CategoriesByID.end(); I != E; ++I)
|
||||
OS << "CATEGORY(\"" << *I << "\")\n";
|
||||
OS << "#endif // GET_CATEGORY_TABLE\n\n";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user