Update llvm and clang to release_38 branch r261369.
This commit is contained in:
parent
2e1a0cbbd8
commit
5082f936dc
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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(); }
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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>;
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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> {
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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':
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
||||||
|
@ -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())
|
||||||
|
@ -7,4 +7,4 @@
|
|||||||
|
|
||||||
#define CLANG_VENDOR "FreeBSD "
|
#define CLANG_VENDOR "FreeBSD "
|
||||||
|
|
||||||
#define SVN_REVISION "260756"
|
#define SVN_REVISION "261369"
|
||||||
|
Loading…
Reference in New Issue
Block a user