Update llvm and clang to release_38 branch r261369.

This commit is contained in:
dim 2016-02-21 16:23:44 +00:00
parent 2e1a0cbbd8
commit 5082f936dc
23 changed files with 370 additions and 354 deletions

View File

@ -544,6 +544,11 @@ namespace llvm {
return true; return true;
} }
// Returns true if any segment in the live range contains any of the
// provided slot indexes. Slots which occur in holes between
// segments will not cause the function to return true.
bool isLiveAtIndexes(ArrayRef<SlotIndex> Slots) const;
bool operator<(const LiveRange& other) const { bool operator<(const LiveRange& other) const {
const SlotIndex &thisIndex = beginIndex(); const SlotIndex &thisIndex = beginIndex();
const SlotIndex &otherIndex = other.beginIndex(); const SlotIndex &otherIndex = other.beginIndex();

View File

@ -1539,16 +1539,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
} }
CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args = None, CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args = None,
ArrayRef<OperandBundleDef> OpBundles = None,
const Twine &Name = "", MDNode *FPMathTag = nullptr) { const Twine &Name = "", MDNode *FPMathTag = nullptr) {
CallInst *CI = CallInst::Create(Callee, Args, OpBundles);
if (isa<FPMathOperator>(CI))
CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF));
return Insert(CI, Name);
}
CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args,
const Twine &Name, MDNode *FPMathTag = nullptr) {
PointerType *PTy = cast<PointerType>(Callee->getType()); PointerType *PTy = cast<PointerType>(Callee->getType());
FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
return CreateCall(FTy, Callee, Args, Name, FPMathTag); return CreateCall(FTy, Callee, Args, Name, FPMathTag);
@ -1563,6 +1554,15 @@ class IRBuilder : public IRBuilderBase, public Inserter {
return Insert(CI, Name); return Insert(CI, Name);
} }
CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> OpBundles,
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
CallInst *CI = CallInst::Create(Callee, Args, OpBundles);
if (isa<FPMathOperator>(CI))
CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF));
return Insert(CI, Name);
}
CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args, CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args,
const Twine &Name = "", MDNode *FPMathTag = nullptr) { const Twine &Name = "", MDNode *FPMathTag = nullptr) {
return CreateCall(Callee->getFunctionType(), Callee, Args, Name, FPMathTag); return CreateCall(Callee->getFunctionType(), Callee, Args, Name, FPMathTag);

View File

@ -2512,6 +2512,14 @@ class PHINode : public Instruction {
return block_begin() + getNumOperands(); return block_begin() + getNumOperands();
} }
iterator_range<block_iterator> blocks() {
return make_range(block_begin(), block_end());
}
iterator_range<const_block_iterator> blocks() const {
return make_range(block_begin(), block_end());
}
op_range incoming_values() { return operands(); } op_range incoming_values() { return operands(); }
const_op_range incoming_values() const { return operands(); } const_op_range incoming_values() const { return operands(); }

View File

@ -213,8 +213,11 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
if (!Spillable) if (!Spillable)
return; return;
// Mark li as unspillable if all live ranges are tiny. // Mark li as unspillable if all live ranges are tiny and the interval
if (li.isZeroLength(LIS.getSlotIndexes())) { // is not live at any reg mask. If the interval is live at a reg mask
// spilling may be required.
if (li.isZeroLength(LIS.getSlotIndexes()) &&
!li.isLiveAtIndexes(LIS.getRegMaskSlots())) {
li.markNotSpillable(); li.markNotSpillable();
return; return;
} }

View File

@ -748,6 +748,40 @@ void LiveRange::flushSegmentSet() {
verify(); verify();
} }
bool LiveRange::isLiveAtIndexes(ArrayRef<SlotIndex> Slots) const {
ArrayRef<SlotIndex>::iterator SlotI = Slots.begin();
ArrayRef<SlotIndex>::iterator SlotE = Slots.end();
// If there are no regmask slots, we have nothing to search.
if (SlotI == SlotE)
return false;
// Start our search at the first segment that ends after the first slot.
const_iterator SegmentI = find(*SlotI);
const_iterator SegmentE = end();
// If there are no segments that end after the first slot, we're done.
if (SegmentI == SegmentE)
return false;
// Look for each slot in the live range.
for ( ; SlotI != SlotE; ++SlotI) {
// Go to the next segment that ends after the current slot.
// The slot may be within a hole in the range.
SegmentI = advanceTo(SegmentI, *SlotI);
if (SegmentI == SegmentE)
return false;
// If this segment contains the slot, we're done.
if (SegmentI->contains(*SlotI))
return true;
// Otherwise, look for the next slot.
}
// We didn't find a segment containing any of the slots.
return false;
}
void LiveInterval::freeSubRange(SubRange *S) { void LiveInterval::freeSubRange(SubRange *S) {
S->~SubRange(); S->~SubRange();
// Memory was allocated with BumpPtr allocator and is not freed here. // Memory was allocated with BumpPtr allocator and is not freed here.

View File

@ -1637,6 +1637,7 @@ struct FloatSignAsInt {
MachinePointerInfo FloatPointerInfo; MachinePointerInfo FloatPointerInfo;
SDValue IntValue; SDValue IntValue;
APInt SignMask; APInt SignMask;
uint8_t SignBit;
}; };
} }
@ -1653,6 +1654,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State,
if (TLI.isTypeLegal(IVT)) { if (TLI.isTypeLegal(IVT)) {
State.IntValue = DAG.getNode(ISD::BITCAST, DL, IVT, Value); State.IntValue = DAG.getNode(ISD::BITCAST, DL, IVT, Value);
State.SignMask = APInt::getSignBit(NumBits); State.SignMask = APInt::getSignBit(NumBits);
State.SignBit = NumBits - 1;
return; return;
} }
@ -1689,6 +1691,7 @@ void SelectionDAGLegalize::getSignAsIntValue(FloatSignAsInt &State,
IntPtr, State.IntPointerInfo, MVT::i8, IntPtr, State.IntPointerInfo, MVT::i8,
false, false, false, 0); false, false, false, 0);
State.SignMask = APInt::getOneBitSet(LoadTy.getSizeInBits(), 7); State.SignMask = APInt::getOneBitSet(LoadTy.getSizeInBits(), 7);
State.SignBit = 7;
} }
/// Replace the integer value produced by getSignAsIntValue() with a new value /// Replace the integer value produced by getSignAsIntValue() with a new value
@ -1731,15 +1734,38 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode *Node) const {
return DAG.getSelect(DL, FloatVT, Cond, NegValue, AbsValue); return DAG.getSelect(DL, FloatVT, Cond, NegValue, AbsValue);
} }
// Transform values to integer, copy the sign bit and transform back. // Transform Mag value to integer, and clear the sign bit.
FloatSignAsInt MagAsInt; FloatSignAsInt MagAsInt;
getSignAsIntValue(MagAsInt, DL, Mag); getSignAsIntValue(MagAsInt, DL, Mag);
assert(SignAsInt.SignMask == MagAsInt.SignMask); EVT MagVT = MagAsInt.IntValue.getValueType();
SDValue ClearSignMask = DAG.getConstant(~SignAsInt.SignMask, DL, IntVT); SDValue ClearSignMask = DAG.getConstant(~MagAsInt.SignMask, DL, MagVT);
SDValue ClearedSign = DAG.getNode(ISD::AND, DL, IntVT, MagAsInt.IntValue, SDValue ClearedSign = DAG.getNode(ISD::AND, DL, MagVT, MagAsInt.IntValue,
ClearSignMask); ClearSignMask);
SDValue CopiedSign = DAG.getNode(ISD::OR, DL, IntVT, ClearedSign, SignBit);
// Get the signbit at the right position for MagAsInt.
int ShiftAmount = SignAsInt.SignBit - MagAsInt.SignBit;
if (SignBit.getValueSizeInBits() > ClearedSign.getValueSizeInBits()) {
if (ShiftAmount > 0) {
SDValue ShiftCnst = DAG.getConstant(ShiftAmount, DL, IntVT);
SignBit = DAG.getNode(ISD::SRL, DL, IntVT, SignBit, ShiftCnst);
} else if (ShiftAmount < 0) {
SDValue ShiftCnst = DAG.getConstant(-ShiftAmount, DL, IntVT);
SignBit = DAG.getNode(ISD::SHL, DL, IntVT, SignBit, ShiftCnst);
}
SignBit = DAG.getNode(ISD::TRUNCATE, DL, MagVT, SignBit);
} else if (SignBit.getValueSizeInBits() < ClearedSign.getValueSizeInBits()) {
SignBit = DAG.getNode(ISD::ZERO_EXTEND, DL, MagVT, SignBit);
if (ShiftAmount > 0) {
SDValue ShiftCnst = DAG.getConstant(ShiftAmount, DL, MagVT);
SignBit = DAG.getNode(ISD::SRL, DL, MagVT, SignBit, ShiftCnst);
} else if (ShiftAmount < 0) {
SDValue ShiftCnst = DAG.getConstant(-ShiftAmount, DL, MagVT);
SignBit = DAG.getNode(ISD::SHL, DL, MagVT, SignBit, ShiftCnst);
}
}
// Store the part with the modified sign and convert back to float.
SDValue CopiedSign = DAG.getNode(ISD::OR, DL, MagVT, ClearedSign, SignBit);
return modifySignAsInt(MagAsInt, DL, CopiedSign); return modifySignAsInt(MagAsInt, DL, CopiedSign);
} }

View File

@ -257,10 +257,14 @@ static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI))
if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest()) if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest())
calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
if (getCleanupRetUnwindDest(InnerCleanupPad) == BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
CatchSwitch->getUnwindDest()) // If a nested cleanup pad reports a null unwind destination and the
// enclosing catch pad doesn't it must be post-dominated by an
// unreachable instruction.
if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
}
} }
} }
int CatchHigh = FuncInfo.getLastStateNumber(); int CatchHigh = FuncInfo.getLastStateNumber();
@ -360,10 +364,14 @@ static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo,
if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI)) if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI))
if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest()) if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest())
calculateSEHStateNumbers(FuncInfo, UserI, ParentState); calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI)) {
if (getCleanupRetUnwindDest(InnerCleanupPad) == BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad);
CatchSwitch->getUnwindDest()) // If a nested cleanup pad reports a null unwind destination and the
// enclosing catch pad doesn't it must be post-dominated by an
// unreachable instruction.
if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest())
calculateSEHStateNumbers(FuncInfo, UserI, ParentState); calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
}
} }
} else { } else {
auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI); auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);

View File

@ -338,9 +338,9 @@ static Triple::ArchType parseArch(StringRef ArchName) {
// FIXME: Do we need to support these? // FIXME: Do we need to support these?
.Cases("i786", "i886", "i986", Triple::x86) .Cases("i786", "i886", "i986", Triple::x86)
.Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64)
.Case("powerpc", Triple::ppc) .Cases("powerpc", "ppc32", Triple::ppc)
.Cases("powerpc64", "ppu", Triple::ppc64) .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64)
.Case("powerpc64le", Triple::ppc64le) .Cases("powerpc64le", "ppc64le", Triple::ppc64le)
.Case("xscale", Triple::arm) .Case("xscale", Triple::arm)
.Case("xscaleeb", Triple::armeb) .Case("xscaleeb", Triple::armeb)
.Case("aarch64", Triple::aarch64) .Case("aarch64", Triple::aarch64)
@ -359,7 +359,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("r600", Triple::r600) .Case("r600", Triple::r600)
.Case("amdgcn", Triple::amdgcn) .Case("amdgcn", Triple::amdgcn)
.Case("hexagon", Triple::hexagon) .Case("hexagon", Triple::hexagon)
.Case("s390x", Triple::systemz) .Cases("s390x", "systemz", Triple::systemz)
.Case("sparc", Triple::sparc) .Case("sparc", Triple::sparc)
.Case("sparcel", Triple::sparcel) .Case("sparcel", Triple::sparcel)
.Cases("sparcv9", "sparc64", Triple::sparcv9) .Cases("sparcv9", "sparc64", Triple::sparcv9)

View File

@ -267,9 +267,9 @@ defm : int_cond_alias<"neg", 0b0110>;
defm : int_cond_alias<"vc", 0b1111>; defm : int_cond_alias<"vc", 0b1111>;
defm : int_cond_alias<"vs", 0b0111>; defm : int_cond_alias<"vs", 0b0111>;
defm : fp_cond_alias<"a", 0b0000>; defm : fp_cond_alias<"a", 0b1000>;
defm : fp_cond_alias<"", 0b0000>; // same as a; gnu asm, not in manual defm : fp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual
defm : fp_cond_alias<"n", 0b1000>; defm : fp_cond_alias<"n", 0b0000>;
defm : fp_cond_alias<"u", 0b0111>; defm : fp_cond_alias<"u", 0b0111>;
defm : fp_cond_alias<"g", 0b0110>; defm : fp_cond_alias<"g", 0b0110>;
defm : fp_cond_alias<"ug", 0b0101>; defm : fp_cond_alias<"ug", 0b0101>;

View File

@ -69,19 +69,15 @@ class X86ELFObjectWriter : public MCELFObjectTargetWriter {
class X86AsmBackend : public MCAsmBackend { class X86AsmBackend : public MCAsmBackend {
const StringRef CPU; const StringRef CPU;
bool HasNopl; bool HasNopl;
uint64_t MaxNopLength; const uint64_t MaxNopLength;
public: public:
X86AsmBackend(const Target &T, StringRef CPU) : MCAsmBackend(), CPU(CPU) { X86AsmBackend(const Target &T, StringRef CPU)
: MCAsmBackend(), CPU(CPU), MaxNopLength(CPU == "slm" ? 7 : 15) {
HasNopl = CPU != "generic" && CPU != "i386" && CPU != "i486" && HasNopl = CPU != "generic" && CPU != "i386" && CPU != "i486" &&
CPU != "i586" && CPU != "pentium" && CPU != "pentium-mmx" && CPU != "i586" && CPU != "pentium" && CPU != "pentium-mmx" &&
CPU != "i686" && CPU != "k6" && CPU != "k6-2" && CPU != "k6-3" && CPU != "i686" && CPU != "k6" && CPU != "k6-2" && CPU != "k6-3" &&
CPU != "geode" && CPU != "winchip-c6" && CPU != "winchip2" && CPU != "geode" && CPU != "winchip-c6" && CPU != "winchip2" &&
CPU != "c3" && CPU != "c3-2"; CPU != "c3" && CPU != "c3-2";
// Max length of true long nop instruction is 15 bytes.
// Max length of long nop replacement instruction is 7 bytes.
// Taking into account SilverMont architecture features max length of nops
// is reduced for it to achieve better performance.
MaxNopLength = (!HasNopl || CPU == "slm") ? 7 : 15;
} }
unsigned getNumFixupKinds() const override { unsigned getNumFixupKinds() const override {
@ -299,7 +295,7 @@ void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
/// bytes. /// bytes.
/// \return - true on success, false on failure /// \return - true on success, false on failure
bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
static const uint8_t TrueNops[10][10] = { static const uint8_t Nops[10][10] = {
// nop // nop
{0x90}, {0x90},
// xchg %ax,%ax // xchg %ax,%ax
@ -322,31 +318,17 @@ bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
{0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
}; };
// Alternative nop instructions for CPUs which don't support long nops. // This CPU doesn't support long nops. If needed add more.
static const uint8_t AltNops[7][10] = { // FIXME: Can we get this from the subtarget somehow?
// nop // FIXME: We could generated something better than plain 0x90.
{0x90}, if (!HasNopl) {
// xchg %ax,%ax for (uint64_t i = 0; i < Count; ++i)
{0x66, 0x90}, OW->write8(0x90);
// lea 0x0(%esi),%esi return true;
{0x8d, 0x76, 0x00}, }
// lea 0x0(%esi),%esi
{0x8d, 0x74, 0x26, 0x00},
// nop + lea 0x0(%esi),%esi
{0x90, 0x8d, 0x74, 0x26, 0x00},
// lea 0x0(%esi),%esi
{0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00 },
// lea 0x0(%esi),%esi
{0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00},
};
// Select the right NOP table. // 15 is the longest single nop instruction. Emit as many 15-byte nops as
// FIXME: Can we get if CPU supports long nops from the subtarget somehow? // needed, then emit a nop of the remaining length.
const uint8_t (*Nops)[10] = HasNopl ? TrueNops : AltNops;
assert(HasNopl || MaxNopLength <= 7);
// Emit as many largest nops as needed, then emit a nop of the remaining
// length.
do { do {
const uint8_t ThisNopLength = (uint8_t) std::min(Count, MaxNopLength); const uint8_t ThisNopLength = (uint8_t) std::min(Count, MaxNopLength);
const uint8_t Prefixes = ThisNopLength <= 10 ? 0 : ThisNopLength - 10; const uint8_t Prefixes = ThisNopLength <= 10 ? 0 : ThisNopLength - 10;

View File

@ -192,10 +192,9 @@ static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,
return 0; return 0;
} }
static bool isEAXLiveIn(MachineFunction &MF) { static bool isEAXLiveIn(MachineBasicBlock &MBB) {
for (MachineRegisterInfo::livein_iterator II = MF.getRegInfo().livein_begin(), for (MachineBasicBlock::RegisterMaskPair RegMask : MBB.liveins()) {
EE = MF.getRegInfo().livein_end(); II != EE; ++II) { unsigned Reg = RegMask.PhysReg;
unsigned Reg = II->first;
if (Reg == X86::RAX || Reg == X86::EAX || Reg == X86::AX || if (Reg == X86::RAX || Reg == X86::EAX || Reg == X86::AX ||
Reg == X86::AH || Reg == X86::AL) Reg == X86::AH || Reg == X86::AL)
@ -261,7 +260,7 @@ void X86FrameLowering::emitSPUpdate(MachineBasicBlock &MBB,
// load the offset into a register and do one sub/add // load the offset into a register and do one sub/add
unsigned Reg = 0; unsigned Reg = 0;
if (isSub && !isEAXLiveIn(*MBB.getParent())) if (isSub && !isEAXLiveIn(MBB))
Reg = (unsigned)(Is64Bit ? X86::RAX : X86::EAX); Reg = (unsigned)(Is64Bit ? X86::RAX : X86::EAX);
else else
Reg = findDeadCallerSavedReg(MBB, MBBI, TRI, Is64Bit); Reg = findDeadCallerSavedReg(MBB, MBBI, TRI, Is64Bit);
@ -1133,8 +1132,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
if (IsWin64Prologue && !IsFunclet && TRI->needsStackRealignment(MF)) if (IsWin64Prologue && !IsFunclet && TRI->needsStackRealignment(MF))
AlignedNumBytes = RoundUpToAlignment(AlignedNumBytes, MaxAlign); AlignedNumBytes = RoundUpToAlignment(AlignedNumBytes, MaxAlign);
if (AlignedNumBytes >= StackProbeSize && UseStackProbe) { if (AlignedNumBytes >= StackProbeSize && UseStackProbe) {
// Check whether EAX is livein for this function. // Check whether EAX is livein for this block.
bool isEAXAlive = isEAXLiveIn(MF); bool isEAXAlive = isEAXLiveIn(MBB);
if (isEAXAlive) { if (isEAXAlive) {
// Sanity check that EAX is not livein for this function. // Sanity check that EAX is not livein for this function.

View File

@ -5896,7 +5896,7 @@ multiclass avx512_sqrt_scalar<bits<8> opc, string OpcodeStr,X86VectorVTInfo _,
def : Pat<(_.EltVT (OpNode (load addr:$src))), def : Pat<(_.EltVT (OpNode (load addr:$src))),
(!cast<Instruction>(NAME#SUFF#Zm) (!cast<Instruction>(NAME#SUFF#Zm)
(_.EltVT (IMPLICIT_DEF)), addr:$src)>, Requires<[OptForSize]>; (_.EltVT (IMPLICIT_DEF)), addr:$src)>, Requires<[HasAVX512, OptForSize]>;
} }
multiclass avx512_sqrt_scalar_all<bits<8> opc, string OpcodeStr> { multiclass avx512_sqrt_scalar_all<bits<8> opc, string OpcodeStr> {

View File

@ -29,6 +29,7 @@
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/Transforms/Utils/Local.h"
#include <algorithm> #include <algorithm>
using namespace llvm; using namespace llvm;
@ -186,32 +187,8 @@ bool PruneEH::SimplifyFunction(Function *F) {
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(F)) { if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(F)) {
SmallVector<Value*, 8> Args(II->arg_begin(), II->arg_end());
SmallVector<OperandBundleDef, 1> OpBundles;
II->getOperandBundlesAsDefs(OpBundles);
// Insert a call instruction before the invoke.
CallInst *Call = CallInst::Create(II->getCalledValue(), Args, OpBundles,
"", II);
Call->takeName(II);
Call->setCallingConv(II->getCallingConv());
Call->setAttributes(II->getAttributes());
Call->setDebugLoc(II->getDebugLoc());
// Anything that used the value produced by the invoke instruction
// now uses the value produced by the call instruction. Note that we
// do this even for void functions and calls with no uses so that the
// callgraph edge is updated.
II->replaceAllUsesWith(Call);
BasicBlock *UnwindBlock = II->getUnwindDest(); BasicBlock *UnwindBlock = II->getUnwindDest();
UnwindBlock->removePredecessor(II->getParent()); removeUnwindEdge(&*BB);
// Insert a branch to the normal destination right before the
// invoke.
BranchInst::Create(II->getNormalDest(), II);
// Finally, delete the invoke instruction!
BB->getInstList().pop_back();
// If the unwind block is now dead, nuke it. // If the unwind block is now dead, nuke it.
if (pred_empty(UnwindBlock)) if (pred_empty(UnwindBlock))
@ -251,23 +228,39 @@ void PruneEH::DeleteBasicBlock(BasicBlock *BB) {
assert(pred_empty(BB) && "BB is not dead!"); assert(pred_empty(BB) && "BB is not dead!");
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
Instruction *TokenInst = nullptr;
CallGraphNode *CGN = CG[BB->getParent()]; CallGraphNode *CGN = CG[BB->getParent()];
for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) {
--I; --I;
if (CallInst *CI = dyn_cast<CallInst>(I)) {
if (!isa<IntrinsicInst>(I)) if (I->getType()->isTokenTy()) {
CGN->removeCallEdgeFor(CI); TokenInst = &*I;
} else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) break;
CGN->removeCallEdgeFor(II); }
if (auto CS = CallSite (&*I)) {
const Function *Callee = CS.getCalledFunction();
if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID()))
CGN->removeCallEdgeFor(CS);
else if (!Callee->isIntrinsic())
CGN->removeCallEdgeFor(CS);
}
if (!I->use_empty()) if (!I->use_empty())
I->replaceAllUsesWith(UndefValue::get(I->getType())); I->replaceAllUsesWith(UndefValue::get(I->getType()));
} }
// Get the list of successors of this block. if (TokenInst) {
std::vector<BasicBlock*> Succs(succ_begin(BB), succ_end(BB)); if (!isa<TerminatorInst>(TokenInst))
changeToUnreachable(TokenInst->getNextNode(), /*UseLLVMTrap=*/false);
} else {
// Get the list of successors of this block.
std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB));
for (unsigned i = 0, e = Succs.size(); i != e; ++i) for (unsigned i = 0, e = Succs.size(); i != e; ++i)
Succs[i]->removePredecessor(BB); Succs[i]->removePredecessor(BB);
BB->eraseFromParent(); BB->eraseFromParent();
}
} }

View File

@ -4799,6 +4799,17 @@ LSRInstance::LSRInstance(Loop *L, IVUsers &IU, ScalarEvolution &SE,
DEBUG(dbgs() << "LSR skipping loop, too many IV Users in " << U << "\n"); DEBUG(dbgs() << "LSR skipping loop, too many IV Users in " << U << "\n");
return; return;
} }
// Bail out if we have a PHI on an EHPad that gets a value from a
// CatchSwitchInst. Because the CatchSwitchInst cannot be split, there is
// no good place to stick any instructions.
if (auto *PN = dyn_cast<PHINode>(U.getUser())) {
auto *FirstNonPHI = PN->getParent()->getFirstNonPHI();
if (isa<FuncletPadInst>(FirstNonPHI) ||
isa<CatchSwitchInst>(FirstNonPHI))
for (BasicBlock *PredBB : PN->blocks())
if (isa<CatchSwitchInst>(PredBB->getFirstNonPHI()))
return;
}
} }
#ifndef NDEBUG #ifndef NDEBUG

View File

@ -1409,14 +1409,15 @@ class LoopVectorizationLegality {
/// different operations. /// different operations.
class LoopVectorizationCostModel { class LoopVectorizationCostModel {
public: public:
LoopVectorizationCostModel(Loop *L, PredicatedScalarEvolution &PSE, LoopVectorizationCostModel(Loop *L, ScalarEvolution *SE, LoopInfo *LI,
LoopInfo *LI, LoopVectorizationLegality *Legal, LoopVectorizationLegality *Legal,
const TargetTransformInfo &TTI, const TargetTransformInfo &TTI,
const TargetLibraryInfo *TLI, DemandedBits *DB, const TargetLibraryInfo *TLI, DemandedBits *DB,
AssumptionCache *AC, const Function *F, AssumptionCache *AC, const Function *F,
const LoopVectorizeHints *Hints) const LoopVectorizeHints *Hints,
: TheLoop(L), PSE(PSE), LI(LI), Legal(Legal), TTI(TTI), TLI(TLI), DB(DB), SmallPtrSetImpl<const Value *> &ValuesToIgnore)
AC(AC), TheFunction(F), Hints(Hints) {} : TheLoop(L), SE(SE), LI(LI), Legal(Legal), TTI(TTI), TLI(TLI), DB(DB),
TheFunction(F), Hints(Hints), ValuesToIgnore(ValuesToIgnore) {}
/// Information about vectorization costs /// Information about vectorization costs
struct VectorizationFactor { struct VectorizationFactor {
@ -1464,9 +1465,6 @@ class LoopVectorizationCostModel {
SmallVector<RegisterUsage, 8> SmallVector<RegisterUsage, 8>
calculateRegisterUsage(const SmallVector<unsigned, 8> &VFs); calculateRegisterUsage(const SmallVector<unsigned, 8> &VFs);
/// Collect values we want to ignore in the cost model.
void collectValuesToIgnore();
private: private:
/// Returns the expected execution cost. The unit of the cost does /// Returns the expected execution cost. The unit of the cost does
/// not matter because we use the 'cost' units to compare different /// not matter because we use the 'cost' units to compare different
@ -1498,8 +1496,8 @@ class LoopVectorizationCostModel {
/// The loop that we evaluate. /// The loop that we evaluate.
Loop *TheLoop; Loop *TheLoop;
/// Predicated scalar evolution analysis. /// Scev analysis.
PredicatedScalarEvolution &PSE; ScalarEvolution *SE;
/// Loop Info analysis. /// Loop Info analysis.
LoopInfo *LI; LoopInfo *LI;
/// Vectorization legality. /// Vectorization legality.
@ -1508,17 +1506,13 @@ class LoopVectorizationCostModel {
const TargetTransformInfo &TTI; const TargetTransformInfo &TTI;
/// Target Library Info. /// Target Library Info.
const TargetLibraryInfo *TLI; const TargetLibraryInfo *TLI;
/// Demanded bits analysis. /// Demanded bits analysis
DemandedBits *DB; DemandedBits *DB;
/// Assumption cache.
AssumptionCache *AC;
const Function *TheFunction; const Function *TheFunction;
/// Loop Vectorize Hint. // Loop Vectorize Hint.
const LoopVectorizeHints *Hints; const LoopVectorizeHints *Hints;
/// Values to ignore in the cost model. // Values to ignore in the cost model.
SmallPtrSet<const Value *, 16> ValuesToIgnore; const SmallPtrSetImpl<const Value *> &ValuesToIgnore;
/// Values to ignore in the cost model when VF > 1.
SmallPtrSet<const Value *, 16> VecValuesToIgnore;
}; };
/// \brief This holds vectorization requirements that must be verified late in /// \brief This holds vectorization requirements that must be verified late in
@ -1763,10 +1757,19 @@ struct LoopVectorize : public FunctionPass {
return false; return false;
} }
// Collect values we want to ignore in the cost model. This includes
// type-promoting instructions we identified during reduction detection.
SmallPtrSet<const Value *, 32> ValuesToIgnore;
CodeMetrics::collectEphemeralValues(L, AC, ValuesToIgnore);
for (auto &Reduction : *LVL.getReductionVars()) {
RecurrenceDescriptor &RedDes = Reduction.second;
SmallPtrSetImpl<Instruction *> &Casts = RedDes.getCastInsts();
ValuesToIgnore.insert(Casts.begin(), Casts.end());
}
// Use the cost model. // Use the cost model.
LoopVectorizationCostModel CM(L, PSE, LI, &LVL, *TTI, TLI, DB, AC, F, LoopVectorizationCostModel CM(L, PSE.getSE(), LI, &LVL, *TTI, TLI, DB, AC,
&Hints); F, &Hints, ValuesToIgnore);
CM.collectValuesToIgnore();
// Check the function attributes to find out if this function should be // Check the function attributes to find out if this function should be
// optimized for size. // optimized for size.
@ -4636,6 +4639,8 @@ void InterleavedAccessInfo::analyzeInterleaving(
// Holds all interleaved store groups temporarily. // Holds all interleaved store groups temporarily.
SmallSetVector<InterleaveGroup *, 4> StoreGroups; SmallSetVector<InterleaveGroup *, 4> StoreGroups;
// Holds all interleaved load groups temporarily.
SmallSetVector<InterleaveGroup *, 4> LoadGroups;
// Search the load-load/write-write pair B-A in bottom-up order and try to // Search the load-load/write-write pair B-A in bottom-up order and try to
// insert B into the interleave group of A according to 3 rules: // insert B into the interleave group of A according to 3 rules:
@ -4663,6 +4668,8 @@ void InterleavedAccessInfo::analyzeInterleaving(
if (A->mayWriteToMemory()) if (A->mayWriteToMemory())
StoreGroups.insert(Group); StoreGroups.insert(Group);
else
LoadGroups.insert(Group);
for (auto II = std::next(I); II != E; ++II) { for (auto II = std::next(I); II != E; ++II) {
Instruction *B = II->first; Instruction *B = II->first;
@ -4710,6 +4717,12 @@ void InterleavedAccessInfo::analyzeInterleaving(
for (InterleaveGroup *Group : StoreGroups) for (InterleaveGroup *Group : StoreGroups)
if (Group->getNumMembers() != Group->getFactor()) if (Group->getNumMembers() != Group->getFactor())
releaseGroup(Group); releaseGroup(Group);
// Remove interleaved load groups that don't have the first and last member.
// This guarantees that we won't do speculative out of bounds loads.
for (InterleaveGroup *Group : LoadGroups)
if (!Group->getMember(0) || !Group->getMember(Group->getFactor() - 1))
releaseGroup(Group);
} }
LoopVectorizationCostModel::VectorizationFactor LoopVectorizationCostModel::VectorizationFactor
@ -4734,7 +4747,7 @@ LoopVectorizationCostModel::selectVectorizationFactor(bool OptForSize) {
} }
// Find the trip count. // Find the trip count.
unsigned TC = PSE.getSE()->getSmallConstantTripCount(TheLoop); unsigned TC = SE->getSmallConstantTripCount(TheLoop);
DEBUG(dbgs() << "LV: Found trip count: " << TC << '\n'); DEBUG(dbgs() << "LV: Found trip count: " << TC << '\n');
MinBWs = computeMinimumValueSizes(TheLoop->getBlocks(), *DB, &TTI); MinBWs = computeMinimumValueSizes(TheLoop->getBlocks(), *DB, &TTI);
@ -4936,7 +4949,7 @@ unsigned LoopVectorizationCostModel::selectInterleaveCount(bool OptForSize,
return 1; return 1;
// Do not interleave loops with a relatively small trip count. // Do not interleave loops with a relatively small trip count.
unsigned TC = PSE.getSE()->getSmallConstantTripCount(TheLoop); unsigned TC = SE->getSmallConstantTripCount(TheLoop);
if (TC > 1 && TC < TinyTripCountInterleaveThreshold) if (TC > 1 && TC < TinyTripCountInterleaveThreshold)
return 1; return 1;
@ -5164,15 +5177,15 @@ LoopVectorizationCostModel::calculateRegisterUsage(
// Ignore instructions that are never used within the loop. // Ignore instructions that are never used within the loop.
if (!Ends.count(I)) continue; if (!Ends.count(I)) continue;
// Skip ignored values.
if (ValuesToIgnore.count(I))
continue;
// Remove all of the instructions that end at this location. // Remove all of the instructions that end at this location.
InstrList &List = TransposeEnds[i]; InstrList &List = TransposeEnds[i];
for (unsigned int j = 0, e = List.size(); j < e; ++j) for (unsigned int j = 0, e = List.size(); j < e; ++j)
OpenIntervals.erase(List[j]); OpenIntervals.erase(List[j]);
// Skip ignored values.
if (ValuesToIgnore.count(I))
continue;
// For each VF find the maximum usage of registers. // For each VF find the maximum usage of registers.
for (unsigned j = 0, e = VFs.size(); j < e; ++j) { for (unsigned j = 0, e = VFs.size(); j < e; ++j) {
if (VFs[j] == 1) { if (VFs[j] == 1) {
@ -5182,12 +5195,8 @@ LoopVectorizationCostModel::calculateRegisterUsage(
// Count the number of live intervals. // Count the number of live intervals.
unsigned RegUsage = 0; unsigned RegUsage = 0;
for (auto Inst : OpenIntervals) { for (auto Inst : OpenIntervals)
// Skip ignored values for VF > 1.
if (VecValuesToIgnore.count(Inst))
continue;
RegUsage += GetRegUsage(Inst->getType(), VFs[j]); RegUsage += GetRegUsage(Inst->getType(), VFs[j]);
}
MaxUsages[j] = std::max(MaxUsages[j], RegUsage); MaxUsages[j] = std::max(MaxUsages[j], RegUsage);
} }
@ -5331,7 +5340,6 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, unsigned VF) {
if (VF > 1 && MinBWs.count(I)) if (VF > 1 && MinBWs.count(I))
RetTy = IntegerType::get(RetTy->getContext(), MinBWs[I]); RetTy = IntegerType::get(RetTy->getContext(), MinBWs[I]);
Type *VectorTy = ToVectorTy(RetTy, VF); Type *VectorTy = ToVectorTy(RetTy, VF);
auto SE = PSE.getSE();
// TODO: We need to estimate the cost of intrinsic calls. // TODO: We need to estimate the cost of intrinsic calls.
switch (I->getOpcode()) { switch (I->getOpcode()) {
@ -5633,79 +5641,6 @@ bool LoopVectorizationCostModel::isConsecutiveLoadOrStore(Instruction *Inst) {
return false; return false;
} }
void LoopVectorizationCostModel::collectValuesToIgnore() {
// Ignore ephemeral values.
CodeMetrics::collectEphemeralValues(TheLoop, AC, ValuesToIgnore);
// Ignore type-promoting instructions we identified during reduction
// detection.
for (auto &Reduction : *Legal->getReductionVars()) {
RecurrenceDescriptor &RedDes = Reduction.second;
SmallPtrSetImpl<Instruction *> &Casts = RedDes.getCastInsts();
VecValuesToIgnore.insert(Casts.begin(), Casts.end());
}
// Ignore induction phis that are only used in either GetElementPtr or ICmp
// instruction to exit loop. Induction variables usually have large types and
// can have big impact when estimating register usage.
// This is for when VF > 1.
for (auto &Induction : *Legal->getInductionVars()) {
auto *PN = Induction.first;
auto *UpdateV = PN->getIncomingValueForBlock(TheLoop->getLoopLatch());
// Check that the PHI is only used by the induction increment (UpdateV) or
// by GEPs. Then check that UpdateV is only used by a compare instruction or
// the loop header PHI.
// FIXME: Need precise def-use analysis to determine if this instruction
// variable will be vectorized.
if (std::all_of(PN->user_begin(), PN->user_end(),
[&](const User *U) -> bool {
return U == UpdateV || isa<GetElementPtrInst>(U);
}) &&
std::all_of(UpdateV->user_begin(), UpdateV->user_end(),
[&](const User *U) -> bool {
return U == PN || isa<ICmpInst>(U);
})) {
VecValuesToIgnore.insert(PN);
VecValuesToIgnore.insert(UpdateV);
}
}
// Ignore instructions that will not be vectorized.
// This is for when VF > 1.
for (auto bb = TheLoop->block_begin(), be = TheLoop->block_end(); bb != be;
++bb) {
for (auto &Inst : **bb) {
switch (Inst.getOpcode()) {
case Instruction::GetElementPtr: {
// Ignore GEP if its last operand is an induction variable so that it is
// a consecutive load/store and won't be vectorized as scatter/gather
// pattern.
GetElementPtrInst *Gep = cast<GetElementPtrInst>(&Inst);
unsigned NumOperands = Gep->getNumOperands();
unsigned InductionOperand = getGEPInductionOperand(Gep);
bool GepToIgnore = true;
// Check that all of the gep indices are uniform except for the
// induction operand.
for (unsigned i = 0; i != NumOperands; ++i) {
if (i != InductionOperand &&
!PSE.getSE()->isLoopInvariant(PSE.getSCEV(Gep->getOperand(i)),
TheLoop)) {
GepToIgnore = false;
break;
}
}
if (GepToIgnore)
VecValuesToIgnore.insert(&Inst);
break;
}
}
}
}
}
void InnerLoopUnroller::scalarizeInstruction(Instruction *Instr, void InnerLoopUnroller::scalarizeInstruction(Instruction *Instr,
bool IfPredicateStore) { bool IfPredicateStore) {

View File

@ -4915,8 +4915,8 @@ class ARMTargetInfo : public TargetInfo {
default: break; default: break;
case 'l': // r0-r7 case 'l': // r0-r7
case 'h': // r8-r15 case 'h': // r8-r15
case 'w': // VFP Floating point register single precision case 't': // VFP Floating point register single precision
case 'P': // VFP Floating point register double precision case 'w': // VFP Floating point register double precision
Info.setAllowsRegister(); Info.setAllowsRegister();
return true; return true;
case 'I': case 'I':

View File

@ -585,71 +585,48 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
EmitBlock(ThenBB); EmitBlock(ThenBB);
} }
llvm::DenseMap<const Decl *, const Expr *> LoopCountersAndUpdates; llvm::DenseMap<const Decl *, const Expr *> LoopCountersAndUpdates;
const Expr *LastIterVal = nullptr;
const Expr *IVExpr = nullptr;
const Expr *IncExpr = nullptr;
if (auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) { if (auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
if (isOpenMPWorksharingDirective(D.getDirectiveKind())) { auto IC = LoopDirective->counters().begin();
LastIterVal = cast<VarDecl>(cast<DeclRefExpr>( for (auto F : LoopDirective->finals()) {
LoopDirective->getUpperBoundVariable()) auto *D = cast<DeclRefExpr>(*IC)->getDecl()->getCanonicalDecl();
->getDecl()) LoopCountersAndUpdates[D] = F;
->getAnyInitializer(); ++IC;
IVExpr = LoopDirective->getIterationVariable();
IncExpr = LoopDirective->getInc();
auto IUpdate = LoopDirective->updates().begin();
for (auto *E : LoopDirective->counters()) {
auto *D = cast<DeclRefExpr>(E)->getDecl()->getCanonicalDecl();
LoopCountersAndUpdates[D] = *IUpdate;
++IUpdate;
}
} }
} }
{ llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
bool FirstLCV = true; auto IRef = C->varlist_begin();
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { auto ISrcRef = C->source_exprs().begin();
auto IRef = C->varlist_begin(); auto IDestRef = C->destination_exprs().begin();
auto ISrcRef = C->source_exprs().begin(); for (auto *AssignOp : C->assignment_ops()) {
auto IDestRef = C->destination_exprs().begin(); auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
for (auto *AssignOp : C->assignment_ops()) { QualType Type = PrivateVD->getType();
auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); auto *CanonicalVD = PrivateVD->getCanonicalDecl();
QualType Type = PrivateVD->getType(); if (AlreadyEmittedVars.insert(CanonicalVD).second) {
auto *CanonicalVD = PrivateVD->getCanonicalDecl(); // If lastprivate variable is a loop control variable for loop-based
if (AlreadyEmittedVars.insert(CanonicalVD).second) { // directive, update its value before copyin back to original
// If lastprivate variable is a loop control variable for loop-based // variable.
// directive, update its value before copyin back to original if (auto *UpExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
// variable. EmitIgnoredExpr(UpExpr);
if (auto *UpExpr = LoopCountersAndUpdates.lookup(CanonicalVD)) { auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
if (FirstLCV && LastIterVal) { auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
EmitAnyExprToMem(LastIterVal, EmitLValue(IVExpr).getAddress(), // Get the address of the original variable.
IVExpr->getType().getQualifiers(), Address OriginalAddr = GetAddrOfLocalVar(DestVD);
/*IsInitializer=*/false); // Get the address of the private variable.
EmitIgnoredExpr(IncExpr); Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
FirstLCV = false; if (auto RefTy = PrivateVD->getType()->getAs<ReferenceType>())
} PrivateAddr =
EmitIgnoredExpr(UpExpr);
}
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
// Get the address of the original variable.
Address OriginalAddr = GetAddrOfLocalVar(DestVD);
// Get the address of the private variable.
Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
if (auto RefTy = PrivateVD->getType()->getAs<ReferenceType>())
PrivateAddr =
Address(Builder.CreateLoad(PrivateAddr), Address(Builder.CreateLoad(PrivateAddr),
getNaturalTypeAlignment(RefTy->getPointeeType())); getNaturalTypeAlignment(RefTy->getPointeeType()));
EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp); EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
}
++IRef;
++ISrcRef;
++IDestRef;
} }
++IRef;
++ISrcRef;
++IDestRef;
} }
} }
if (IsLastIterCond) { if (IsLastIterCond)
EmitBlock(DoneBB, /*IsFinished=*/true); EmitBlock(DoneBB, /*IsFinished=*/true);
}
} }
void CodeGenFunction::EmitOMPReductionClauseInit( void CodeGenFunction::EmitOMPReductionClauseInit(
@ -919,10 +896,6 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
// The end (updates/cleanups). // The end (updates/cleanups).
EmitBlock(Continue.getBlock()); EmitBlock(Continue.getBlock());
BreakContinueStack.pop_back(); BreakContinueStack.pop_back();
// TODO: Update lastprivates if the SeparateIter flag is true.
// This will be implemented in a follow-up OMPLastprivateClause patch, but
// result should be still correct without it, as we do not make these
// variables private yet.
} }
void CodeGenFunction::EmitOMPInnerLoop( void CodeGenFunction::EmitOMPInnerLoop(

View File

@ -4868,9 +4868,6 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
}; };
class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo { class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo {
void addStackProbeSizeTargetAttribute(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const;
public: public:
WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K) WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K)
: ARMTargetCodeGenInfo(CGT, K) {} : ARMTargetCodeGenInfo(CGT, K) {}
@ -4879,18 +4876,6 @@ class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo {
CodeGen::CodeGenModule &CGM) const override; CodeGen::CodeGenModule &CGM) const override;
}; };
void WindowsARMTargetCodeGenInfo::addStackProbeSizeTargetAttribute(
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
if (!isa<FunctionDecl>(D))
return;
if (CGM.getCodeGenOpts().StackProbeSize == 4096)
return;
llvm::Function *F = cast<llvm::Function>(GV);
F->addFnAttr("stack-probe-size",
llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
}
void WindowsARMTargetCodeGenInfo::setTargetAttributes( void WindowsARMTargetCodeGenInfo::setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM); ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);

View File

@ -3108,6 +3108,22 @@ void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
} }
} }
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
bool Profiling = Args.hasArg(options::OPT_pg);
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
break;
}
}
Tool *FreeBSD::buildAssembler() const { Tool *FreeBSD::buildAssembler() const {
return new tools::freebsd::Assembler(*this); return new tools::freebsd::Assembler(*this);
} }

View File

@ -722,6 +722,8 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
void AddClangCXXStdlibIncludeArgs( void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override; llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override; bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault() const override; bool isPIEDefault() const override;

View File

@ -182,7 +182,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true; return true;
unsigned NewLineColumn = getNewLineColumn(State); unsigned NewLineColumn = getNewLineColumn(State);
if (Current.isMemberAccess() && if (Current.isMemberAccess() && Style.ColumnLimit != 0 &&
State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit && State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit &&
(State.Column > NewLineColumn || (State.Column > NewLineColumn ||
Current.NestingLevel < State.StartOfLineLevel)) Current.NestingLevel < State.StartOfLineLevel))

View File

@ -634,7 +634,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
if (auto *CTD = CTSD->getSpecializedTemplate()) if (auto *CTD = CTSD->getSpecializedTemplate())
RD = CTD->getTemplatedDecl(); RD = CTD->getTemplatedDecl();
if (IsConstant && if (IsConstant &&
!(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) { !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasDefinition() &&
RD->hasMutableFields())) {
// Variables with const-qualified type having no mutable member may be // Variables with const-qualified type having no mutable member may be
// listed in a firstprivate clause, even if they are static data members. // listed in a firstprivate clause, even if they are static data members.
DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate), DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
@ -3204,7 +3205,7 @@ class TransformToNewDefs : public TreeTransform<TransformToNewDefs> {
NewVD->setInitStyle(VD->getInitStyle()); NewVD->setInitStyle(VD->getInitStyle());
NewVD->setExceptionVariable(VD->isExceptionVariable()); NewVD->setExceptionVariable(VD->isExceptionVariable());
NewVD->setNRVOVariable(VD->isNRVOVariable()); NewVD->setNRVOVariable(VD->isNRVOVariable());
NewVD->setCXXForRangeDecl(VD->isInExternCXXContext()); NewVD->setCXXForRangeDecl(VD->isCXXForRangeDecl());
NewVD->setConstexpr(VD->isConstexpr()); NewVD->setConstexpr(VD->isConstexpr());
NewVD->setInitCapture(VD->isInitCapture()); NewVD->setInitCapture(VD->isInitCapture());
NewVD->setPreviousDeclInSameBlockScope( NewVD->setPreviousDeclInSameBlockScope(
@ -3249,14 +3250,20 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
Expr *Lower = Transform.TransformExpr(LBExpr).get(); Expr *Lower = Transform.TransformExpr(LBExpr).get();
if (!Upper || !Lower) if (!Upper || !Lower)
return nullptr; return nullptr;
Upper = SemaRef.PerformImplicitConversion(Upper, UBExpr->getType(), if (!SemaRef.Context.hasSameType(Upper->getType(), UBExpr->getType())) {
Sema::AA_Converting, Upper = SemaRef
/*AllowExplicit=*/true) .PerformImplicitConversion(Upper, UBExpr->getType(),
.get(); Sema::AA_Converting,
Lower = SemaRef.PerformImplicitConversion(Lower, LBExpr->getType(), /*AllowExplicit=*/true)
Sema::AA_Converting, .get();
/*AllowExplicit=*/true) }
.get(); if (!SemaRef.Context.hasSameType(Lower->getType(), LBExpr->getType())) {
Lower = SemaRef
.PerformImplicitConversion(Lower, LBExpr->getType(),
Sema::AA_Converting,
/*AllowExplicit=*/true)
.get();
}
if (!Upper || !Lower) if (!Upper || !Lower)
return nullptr; return nullptr;
@ -3283,14 +3290,18 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
return nullptr; return nullptr;
// Upper - Lower [- 1] + Step // Upper - Lower [- 1] + Step
auto NewStep = Transform.TransformExpr(Step->IgnoreImplicit()); auto *StepNoImp = Step->IgnoreImplicit();
if (NewStep.isInvalid()) auto NewStep = Transform.TransformExpr(StepNoImp);
return nullptr;
NewStep = SemaRef.PerformImplicitConversion(
NewStep.get(), Step->IgnoreImplicit()->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStep.isInvalid()) if (NewStep.isInvalid())
return nullptr; return nullptr;
if (!SemaRef.Context.hasSameType(NewStep.get()->getType(),
StepNoImp->getType())) {
NewStep = SemaRef.PerformImplicitConversion(
NewStep.get(), StepNoImp->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStep.isInvalid())
return nullptr;
}
Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get()); Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
if (!Diff.isUsable()) if (!Diff.isUsable())
return nullptr; return nullptr;
@ -3301,14 +3312,17 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
return nullptr; return nullptr;
// (Upper - Lower [- 1] + Step) / Step // (Upper - Lower [- 1] + Step) / Step
NewStep = Transform.TransformExpr(Step->IgnoreImplicit()); NewStep = Transform.TransformExpr(StepNoImp);
if (NewStep.isInvalid())
return nullptr;
NewStep = SemaRef.PerformImplicitConversion(
NewStep.get(), Step->IgnoreImplicit()->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStep.isInvalid()) if (NewStep.isInvalid())
return nullptr; return nullptr;
if (!SemaRef.Context.hasSameType(NewStep.get()->getType(),
StepNoImp->getType())) {
NewStep = SemaRef.PerformImplicitConversion(
NewStep.get(), StepNoImp->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStep.isInvalid())
return nullptr;
}
Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
if (!Diff.isUsable()) if (!Diff.isUsable())
return nullptr; return nullptr;
@ -3324,10 +3338,12 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation() bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
: Type->hasSignedIntegerRepresentation(); : Type->hasSignedIntegerRepresentation();
Type = C.getIntTypeForBitwidth(NewSize, IsSigned); Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
Diff = SemaRef.PerformImplicitConversion( if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true); Diff = SemaRef.PerformImplicitConversion(
if (!Diff.isUsable()) Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
return nullptr; if (!Diff.isUsable())
return nullptr;
}
} }
if (LimitedType) { if (LimitedType) {
unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32; unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
@ -3340,10 +3356,12 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S,
QualType NewType = C.getIntTypeForBitwidth( QualType NewType = C.getIntTypeForBitwidth(
NewSize, Type->hasSignedIntegerRepresentation() || NewSize, Type->hasSignedIntegerRepresentation() ||
C.getTypeSize(Type) < NewSize); C.getTypeSize(Type) < NewSize);
Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType, if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
Sema::AA_Converting, true); Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
if (!Diff.isUsable()) Sema::AA_Converting, true);
return nullptr; if (!Diff.isUsable())
return nullptr;
}
} }
} }
@ -3360,12 +3378,16 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {
auto NewUB = Transform.TransformExpr(UB); auto NewUB = Transform.TransformExpr(UB);
if (NewLB.isInvalid() || NewUB.isInvalid()) if (NewLB.isInvalid() || NewUB.isInvalid())
return Cond; return Cond;
NewLB = SemaRef.PerformImplicitConversion(NewLB.get(), LB->getType(), if (!SemaRef.Context.hasSameType(NewLB.get()->getType(), LB->getType())) {
Sema::AA_Converting, NewLB = SemaRef.PerformImplicitConversion(NewLB.get(), LB->getType(),
/*AllowExplicit=*/true); Sema::AA_Converting,
NewUB = SemaRef.PerformImplicitConversion(NewUB.get(), UB->getType(), /*AllowExplicit=*/true);
Sema::AA_Converting, }
/*AllowExplicit=*/true); if (!SemaRef.Context.hasSameType(NewUB.get()->getType(), UB->getType())) {
NewUB = SemaRef.PerformImplicitConversion(NewUB.get(), UB->getType(),
Sema::AA_Converting,
/*AllowExplicit=*/true);
}
if (NewLB.isInvalid() || NewUB.isInvalid()) if (NewLB.isInvalid() || NewUB.isInvalid())
return Cond; return Cond;
auto CondExpr = SemaRef.BuildBinOp( auto CondExpr = SemaRef.BuildBinOp(
@ -3373,9 +3395,11 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {
: (TestIsStrictOp ? BO_GT : BO_GE), : (TestIsStrictOp ? BO_GT : BO_GE),
NewLB.get(), NewUB.get()); NewLB.get(), NewUB.get());
if (CondExpr.isUsable()) { if (CondExpr.isUsable()) {
CondExpr = SemaRef.PerformImplicitConversion( if (!SemaRef.Context.hasSameType(CondExpr.get()->getType(),
CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting, SemaRef.Context.BoolTy))
/*AllowExplicit=*/true); CondExpr = SemaRef.PerformImplicitConversion(
CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
/*AllowExplicit=*/true);
} }
SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress); SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress);
// Otherwise use original loop conditon and evaluate it in runtime. // Otherwise use original loop conditon and evaluate it in runtime.
@ -3602,20 +3626,26 @@ static ExprResult BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc,
ExprResult VarRef, ExprResult Start) { ExprResult VarRef, ExprResult Start) {
TransformToNewDefs Transform(SemaRef); TransformToNewDefs Transform(SemaRef);
// Build 'VarRef = Start. // Build 'VarRef = Start.
auto NewStart = Transform.TransformExpr(Start.get()->IgnoreImplicit()); auto *StartNoImp = Start.get()->IgnoreImplicit();
auto NewStart = Transform.TransformExpr(StartNoImp);
if (NewStart.isInvalid()) if (NewStart.isInvalid())
return ExprError(); return ExprError();
NewStart = SemaRef.PerformImplicitConversion( if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
NewStart.get(), Start.get()->IgnoreImplicit()->getType(), StartNoImp->getType())) {
Sema::AA_Converting, NewStart = SemaRef.PerformImplicitConversion(
/*AllowExplicit=*/true); NewStart.get(), StartNoImp->getType(), Sema::AA_Converting,
if (NewStart.isInvalid()) /*AllowExplicit=*/true);
return ExprError(); if (NewStart.isInvalid())
NewStart = SemaRef.PerformImplicitConversion( return ExprError();
NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting, }
/*AllowExplicit=*/true); if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
if (!NewStart.isUsable()) VarRef.get()->getType())) {
return ExprError(); NewStart = SemaRef.PerformImplicitConversion(
NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (!NewStart.isUsable())
return ExprError();
}
auto Init = auto Init =
SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get()); SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
@ -3633,31 +3663,37 @@ static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S,
!Step.isUsable()) !Step.isUsable())
return ExprError(); return ExprError();
auto *StepNoImp = Step.get()->IgnoreImplicit();
TransformToNewDefs Transform(SemaRef); TransformToNewDefs Transform(SemaRef);
auto NewStep = Transform.TransformExpr(Step.get()->IgnoreImplicit()); auto NewStep = Transform.TransformExpr(StepNoImp);
if (NewStep.isInvalid())
return ExprError();
NewStep = SemaRef.PerformImplicitConversion(
NewStep.get(), Step.get()->IgnoreImplicit()->getType(),
Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStep.isInvalid()) if (NewStep.isInvalid())
return ExprError(); return ExprError();
if (!SemaRef.Context.hasSameType(NewStep.get()->getType(),
StepNoImp->getType())) {
NewStep = SemaRef.PerformImplicitConversion(
NewStep.get(), StepNoImp->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStep.isInvalid())
return ExprError();
}
ExprResult Update = ExprResult Update =
SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get()); SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
if (!Update.isUsable()) if (!Update.isUsable())
return ExprError(); return ExprError();
// Build 'VarRef = Start + Iter * Step'. // Build 'VarRef = Start + Iter * Step'.
auto NewStart = Transform.TransformExpr(Start.get()->IgnoreImplicit()); auto *StartNoImp = Start.get()->IgnoreImplicit();
if (NewStart.isInvalid()) auto NewStart = Transform.TransformExpr(StartNoImp);
return ExprError();
NewStart = SemaRef.PerformImplicitConversion(
NewStart.get(), Start.get()->IgnoreImplicit()->getType(),
Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStart.isInvalid()) if (NewStart.isInvalid())
return ExprError(); return ExprError();
if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
StartNoImp->getType())) {
NewStart = SemaRef.PerformImplicitConversion(
NewStart.get(), StartNoImp->getType(), Sema::AA_Converting,
/*AllowExplicit=*/true);
if (NewStart.isInvalid())
return ExprError();
}
Update = SemaRef.BuildBinOp(S, Loc, (Subtract ? BO_Sub : BO_Add), Update = SemaRef.BuildBinOp(S, Loc, (Subtract ? BO_Sub : BO_Add),
NewStart.get(), Update.get()); NewStart.get(), Update.get());
if (!Update.isUsable()) if (!Update.isUsable())

View File

@ -7,4 +7,4 @@
#define CLANG_VENDOR "FreeBSD " #define CLANG_VENDOR "FreeBSD "
#define SVN_REVISION "260756" #define SVN_REVISION "261369"