Skip to content

Commit

Permalink
Merge branch 'main' into hgh/libcxx/P2997R1-Removing-the-common-refer…
Browse files Browse the repository at this point in the history
…ence-requirement-from-the-indirectly-invocable-concepts
  • Loading branch information
H-G-Hristov authored Jul 14, 2024
2 parents c16f814 + a72eed7 commit f6bc576
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 76 deletions.
14 changes: 10 additions & 4 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,16 @@ bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {

// The This pointer is writable in constructors and destructors,
// even if isConst() returns true.
if (const Function *Func = S.Current->getFunction();
Func && (Func->isConstructor() || Func->isDestructor()) &&
Ptr.block() == S.Current->getThis().block()) {
return true;
// TODO(perf): We could be hitting this code path quite a lot in complex
// constructors. Is there a better way to do this?
if (S.Current->getFunction()) {
for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
if (const Function *Func = Frame->getFunction();
Func && (Func->isConstructor() || Func->isDestructor()) &&
Ptr.block() == Frame->getThis().block()) {
return true;
}
}
}

if (!Ptr.isBlockPointer())
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/Interp/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
OS << "->";
}
OS << *F << "(";

F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(),
/*Qualified=*/false);
OS << '(';
unsigned Off = 0;

Off += Func->hasRVO() ? primSize(PT_Ptr) : 0;
Expand Down
30 changes: 10 additions & 20 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,37 +568,27 @@ namespace IncDec {
return 1;
}
static_assert(uninit<int, true, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int, true, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int, true, true>()'}}
static_assert(uninit<int, false, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int, false, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int, false, true>()'}}

static_assert(uninit<float, true, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, true, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, true, true>()'}}
static_assert(uninit<float, false, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, false, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, false, true>()'}}
static_assert(uninit<float, true, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, true, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, true, false>()'}}
static_assert(uninit<float, false, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, false, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, false, false>()'}}

static_assert(uninit<int*, true, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, true, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, true, true>()'}}
static_assert(uninit<int*, false, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, false, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, false, true>()'}}
static_assert(uninit<int*, true, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, true, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, true, false>()'}}
static_assert(uninit<int*, false, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, false, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, false, false>()'}}

constexpr int OverFlow() { // both-error {{never produces a constant expression}}
int a = INT_MAX;
Expand Down
25 changes: 25 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1512,3 +1512,28 @@ namespace OnePastEndAndBack {
constexpr const Base *d = c - 1;
static_assert(d == &a, "");
}

namespace BitSet {
class Bitset {
unsigned Bit = 0;

public:
constexpr Bitset() {
int Init[2] = {1,2};
for (auto I : Init)
set(I);
}
constexpr void set(unsigned I) {
this->Bit++;
this->Bit = 1u << 1;
}
};

struct ArchInfo {
Bitset DefaultExts;
};

constexpr ArchInfo ARMV8A = {
Bitset()
};
}
7 changes: 5 additions & 2 deletions llvm/include/llvm/Analysis/LoopAccessAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ class MemoryDepChecker {

const Loop *getInnermostLoop() const { return InnermostLoop; }

DenseMap<const SCEV *, std::pair<const SCEV *, const SCEV *>> &
DenseMap<std::pair<const SCEV *, Type *>,
std::pair<const SCEV *, const SCEV *>> &
getPointerBounds() {
return PointerBounds;
}
Expand Down Expand Up @@ -334,7 +335,9 @@ class MemoryDepChecker {

/// Mapping of SCEV expressions to their expanded pointer bounds (pair of
/// start and end pointer expressions).
DenseMap<const SCEV *, std::pair<const SCEV *, const SCEV *>> PointerBounds;
DenseMap<std::pair<const SCEV *, Type *>,
std::pair<const SCEV *, const SCEV *>>
PointerBounds;

/// Check whether there is a plausible dependence between the two
/// accesses.
Expand Down
43 changes: 43 additions & 0 deletions llvm/include/llvm/CodeGen/SDPatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,49 @@ template <> struct EffectiveOperands<false> {
explicit EffectiveOperands(SDValue N) : Size(N->getNumOperands()) {}
};

// === Ternary operations ===
template <typename T0_P, typename T1_P, typename T2_P, bool Commutable = false,
bool ExcludeChain = false>
struct TernaryOpc_match {
unsigned Opcode;
T0_P Op0;
T1_P Op1;
T2_P Op2;

TernaryOpc_match(unsigned Opc, const T0_P &Op0, const T1_P &Op1,
const T2_P &Op2)
: Opcode(Opc), Op0(Op0), Op1(Op1), Op2(Op2) {}

template <typename MatchContext>
bool match(const MatchContext &Ctx, SDValue N) {
if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
EffectiveOperands<ExcludeChain> EO(N);
assert(EO.Size == 3);
return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
Op1.match(Ctx, N->getOperand(EO.FirstIndex + 1))) ||
(Commutable && Op0.match(Ctx, N->getOperand(EO.FirstIndex + 1)) &&
Op1.match(Ctx, N->getOperand(EO.FirstIndex)))) &&
Op2.match(Ctx, N->getOperand(EO.FirstIndex + 2));
}

return false;
}
};

template <typename T0_P, typename T1_P, typename T2_P>
inline TernaryOpc_match<T0_P, T1_P, T2_P, false, false>
m_SetCC(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
return TernaryOpc_match<T0_P, T1_P, T2_P, false, false>(ISD::SETCC, Op0, Op1,
Op2);
}

template <typename T0_P, typename T1_P, typename T2_P>
inline TernaryOpc_match<T0_P, T1_P, T2_P, true, false>
m_c_SetCC(const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
return TernaryOpc_match<T0_P, T1_P, T2_P, true, false>(ISD::SETCC, Op0, Op1,
Op2);
}

// === Binary operations ===
template <typename LHS_P, typename RHS_P, bool Commutable = false,
bool ExcludeChain = false>
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/Analysis/LoopAccessAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,13 @@ RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup(
static std::pair<const SCEV *, const SCEV *> getStartAndEndForAccess(
const Loop *Lp, const SCEV *PtrExpr, Type *AccessTy,
PredicatedScalarEvolution &PSE,
DenseMap<const SCEV *, std::pair<const SCEV *, const SCEV *>>
&PointerBounds) {
DenseMap<std::pair<const SCEV *, Type *>,
std::pair<const SCEV *, const SCEV *>> &PointerBounds) {
ScalarEvolution *SE = PSE.getSE();

auto [Iter, Ins] = PointerBounds.insert(
{PtrExpr, {SE->getCouldNotCompute(), SE->getCouldNotCompute()}});
{{PtrExpr, AccessTy},
{SE->getCouldNotCompute(), SE->getCouldNotCompute()}});
if (!Ins)
return Iter->second;

Expand Down
45 changes: 14 additions & 31 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2300,24 +2300,12 @@ static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op,
return true;
}

if (N.getOpcode() != ISD::SETCC ||
N.getValueType().getScalarType() != MVT::i1 ||
cast<CondCodeSDNode>(N.getOperand(2))->get() != ISD::SETNE)
return false;

SDValue Op0 = N->getOperand(0);
SDValue Op1 = N->getOperand(1);
assert(Op0.getValueType() == Op1.getValueType());

if (isNullOrNullSplat(Op0))
Op = Op1;
else if (isNullOrNullSplat(Op1))
Op = Op0;
else
if (N.getValueType().getScalarType() != MVT::i1 ||
!sd_match(
N, m_c_SetCC(m_Value(Op), m_Zero(), m_SpecificCondCode(ISD::SETNE))))
return false;

Known = DAG.computeKnownBits(Op);

return (Known.Zero | 1).isAllOnes();
}

Expand Down Expand Up @@ -2544,26 +2532,22 @@ static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, const SDLoc &DL,
return SDValue();

// Match the zext operand as a setcc of a boolean.
if (Z.getOperand(0).getOpcode() != ISD::SETCC ||
Z.getOperand(0).getValueType() != MVT::i1)
if (Z.getOperand(0).getValueType() != MVT::i1)
return SDValue();

// Match the compare as: setcc (X & 1), 0, eq.
SDValue SetCC = Z.getOperand(0);
ISD::CondCode CC = cast<CondCodeSDNode>(SetCC->getOperand(2))->get();
if (CC != ISD::SETEQ || !isNullConstant(SetCC.getOperand(1)) ||
SetCC.getOperand(0).getOpcode() != ISD::AND ||
!isOneConstant(SetCC.getOperand(0).getOperand(1)))
if (!sd_match(Z.getOperand(0), m_SetCC(m_And(m_Value(), m_One()), m_Zero(),
m_SpecificCondCode(ISD::SETEQ))))
return SDValue();

// We are adding/subtracting a constant and an inverted low bit. Turn that
// into a subtract/add of the low bit with incremented/decremented constant:
// add (zext i1 (seteq (X & 1), 0)), C --> sub C+1, (zext (X & 1))
// sub C, (zext i1 (seteq (X & 1), 0)) --> add C-1, (zext (X & 1))
EVT VT = C.getValueType();
SDValue LowBit = DAG.getZExtOrTrunc(SetCC.getOperand(0), DL, VT);
SDValue C1 = IsAdd ? DAG.getConstant(CN->getAPIntValue() + 1, DL, VT) :
DAG.getConstant(CN->getAPIntValue() - 1, DL, VT);
SDValue LowBit = DAG.getZExtOrTrunc(Z.getOperand(0).getOperand(0), DL, VT);
SDValue C1 = IsAdd ? DAG.getConstant(CN->getAPIntValue() + 1, DL, VT)
: DAG.getConstant(CN->getAPIntValue() - 1, DL, VT);
return DAG.getNode(IsAdd ? ISD::SUB : ISD::ADD, DL, VT, C1, LowBit);
}

Expand Down Expand Up @@ -11554,13 +11538,12 @@ static SDValue foldVSelectToSignBitSplatMask(SDNode *N, SelectionDAG &DAG) {
SDValue N1 = N->getOperand(1);
SDValue N2 = N->getOperand(2);
EVT VT = N->getValueType(0);
if (N0.getOpcode() != ISD::SETCC || !N0.hasOneUse())
return SDValue();

SDValue Cond0 = N0.getOperand(0);
SDValue Cond1 = N0.getOperand(1);
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
if (VT != Cond0.getValueType())
SDValue Cond0, Cond1;
ISD::CondCode CC;
if (!sd_match(N0, m_OneUse(m_SetCC(m_Value(Cond0), m_Value(Cond1),
m_CondCode(CC)))) ||
VT != Cond0.getValueType())
return SDValue();

// Match a signbit check of Cond0 as "Cond0 s<0". Swap select operands if the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"

; FIXME: The runtime checks for A are based on i8 accesses, but should be based
; on i32.
define void @loads_of_same_pointer_with_different_sizes1(ptr %A, ptr %B, i64 %N) {
; CHECK-LABEL: 'loads_of_same_pointer_with_different_sizes1'
; CHECK-NEXT: loop:
Expand All @@ -22,7 +20,7 @@ define void @loads_of_same_pointer_with_different_sizes1(ptr %A, ptr %B, i64 %N)
; CHECK-NEXT: (Low: %B High: ((4 * %N) + %B))
; CHECK-NEXT: Member: {%B,+,4}<nuw><%loop>
; CHECK-NEXT: Group [[GRP2]]:
; CHECK-NEXT: (Low: %A High: (%N + %A))
; CHECK-NEXT: (Low: %A High: (3 + %N + %A))
; CHECK-NEXT: Member: {%A,+,1}<nuw><%loop>
; CHECK-NEXT: Member: {%A,+,1}<nuw><%loop>
; CHECK-EMPTY:
Expand Down Expand Up @@ -101,8 +99,6 @@ exit:
ret void
}

; FIXME: The both runtime checks for A are based on i8 accesses, but one should
; be based on i32.
define void @loads_of_same_pointer_with_different_sizes_retry_with_runtime_checks(ptr %A, ptr %B, i64 %N, i64 %off) {
; CHECK-LABEL: 'loads_of_same_pointer_with_different_sizes_retry_with_runtime_checks'
; CHECK-NEXT: loop:
Expand Down Expand Up @@ -145,7 +141,7 @@ define void @loads_of_same_pointer_with_different_sizes_retry_with_runtime_check
; CHECK-NEXT: (Low: %A High: (%N + %A))
; CHECK-NEXT: Member: {%A,+,1}<nuw><%loop>
; CHECK-NEXT: Group [[GRP8]]:
; CHECK-NEXT: (Low: %A High: (%N + %A))
; CHECK-NEXT: (Low: %A High: (3 + %N + %A))
; CHECK-NEXT: Member: {%A,+,1}<nuw><%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
Expand Down
35 changes: 35 additions & 0 deletions llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,41 @@ TEST_F(SelectionDAGPatternMatchTest, matchValueType) {
EXPECT_FALSE(sd_match(Op2, m_ScalableVectorVT()));
}

TEST_F(SelectionDAGPatternMatchTest, matchTernaryOp) {
SDLoc DL;
auto Int32VT = EVT::getIntegerVT(Context, 32);

SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT);

SDValue ICMP_UGT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGT);
SDValue ICMP_EQ01 = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETEQ);
SDValue ICMP_EQ10 = DAG->getSetCC(DL, MVT::i1, Op1, Op0, ISD::SETEQ);

using namespace SDPatternMatch;
ISD::CondCode CC;
EXPECT_TRUE(sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(),
m_SpecificCondCode(ISD::SETUGT))));
EXPECT_TRUE(
sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_CondCode(CC))));
EXPECT_TRUE(CC == ISD::SETUGT);
EXPECT_FALSE(sd_match(
ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_SpecificCondCode(ISD::SETLE))));

EXPECT_TRUE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op0), m_Specific(Op1),
m_SpecificCondCode(ISD::SETEQ))));
EXPECT_TRUE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op1), m_Specific(Op0),
m_SpecificCondCode(ISD::SETEQ))));
EXPECT_FALSE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op1), m_Specific(Op0),
m_SpecificCondCode(ISD::SETEQ))));
EXPECT_FALSE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op0), m_Specific(Op1),
m_SpecificCondCode(ISD::SETEQ))));
EXPECT_TRUE(sd_match(ICMP_EQ01, m_c_SetCC(m_Specific(Op1), m_Specific(Op0),
m_SpecificCondCode(ISD::SETEQ))));
EXPECT_TRUE(sd_match(ICMP_EQ10, m_c_SetCC(m_Specific(Op0), m_Specific(Op1),
m_SpecificCondCode(ISD::SETEQ))));
}

TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
SDLoc DL;
auto Int32VT = EVT::getIntegerVT(Context, 32);
Expand Down
Loading

0 comments on commit f6bc576

Please sign in to comment.