Skip to content

Commit 52a8213

Browse files
authored
Use memcmp for more array comparisons again (#21647)
As the new compiler logic introduced in #21513 was more simplistic than the previous (templated) implementation in druntime. It e.g. didn't handle comparisons of multi-dimensional static arrays, e.g., `byte[3][3]`, breaking an LDC-specific codegen test.
1 parent bc6dd9d commit 52a8213

1 file changed

Lines changed: 32 additions & 8 deletions

File tree

compiler/src/dmd/expressionsem.d

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3865,9 +3865,28 @@ private extern(C++) final class IsMemcmpableVisitor : Visitor
38653865
public:
38663866
bool result = false;
38673867

3868+
static Type loweredBaseElemOf(Type t)
3869+
{
3870+
t = t.baseElemOf(); // skip over static-array parents
3871+
switch (t.ty)
3872+
{
3873+
case Tvoid:
3874+
return Type.tuns8;
3875+
case Tpointer:
3876+
return Type.tsize_t;
3877+
default:
3878+
return t;
3879+
}
3880+
}
3881+
3882+
static bool isTriviallyMemcmpable(Type t)
3883+
{
3884+
return loweredBaseElemOf(t).isIntegral();
3885+
}
3886+
38683887
override void visit(Type t)
38693888
{
3870-
result = t.ty == Tvoid || (t.isScalar() && !t.isFloating());
3889+
result = isTriviallyMemcmpable(t);
38713890
}
38723891

38733892
override void visit(TypeStruct ts)
@@ -13494,15 +13513,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
1349413513
{
1349513514
Type t1n = t1.nextOf().toBasetype();
1349613515
Type t2n = t2.nextOf().toBasetype();
13497-
const t1nsz = t1n.size();
13498-
const t2nsz = t2n.size();
1349913516

13500-
if ((t1n.ty == Tvoid || (t1n.isScalar() && !t1n.isFloating())) &&
13501-
(t2n.ty == Tvoid || (t2n.isScalar() && !t1n.isFloating())) &&
13502-
t1nsz == t2nsz && t1n.isUnsigned() == t2n.isUnsigned())
13517+
if (t1n.size() != t2n.size())
13518+
return false;
13519+
13520+
if (IsMemcmpableVisitor.isTriviallyMemcmpable(t1n) &&
13521+
IsMemcmpableVisitor.isTriviallyMemcmpable(t2n))
1350313522
{
13504-
return true;
13523+
// due to int promotion, disallow small integers of diverging signed-ness
13524+
Type e1 = IsMemcmpableVisitor.loweredBaseElemOf(t1n);
13525+
Type e2 = IsMemcmpableVisitor.loweredBaseElemOf(t2n);
13526+
if ((e1.size() >= 4 && e2.size() >= 4) || e1.isUnsigned() == e2.isUnsigned())
13527+
return true;
1350513528
}
13529+
1350613530
if (t1n.constOf() != t2n.constOf())
1350713531
{
1350813532
return false;
@@ -13517,7 +13541,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
1351713541
if (global.params.useTypeInfo && Type.dtypeinfo)
1351813542
semanticTypeInfo(sc, ts);
1351913543

13520-
auto v = new IsMemcmpableVisitor();
13544+
scope v = new IsMemcmpableVisitor();
1352113545
ts.accept(v);
1352213546
return v.result;
1352313547
}

0 commit comments

Comments
 (0)