Skip to content

cmd/compile: for always negative numbers int(x) < int(y) proves uint(x) < uint(y) #76722

@Jorropo

Description

@Jorropo

The ssa.limit prove code widely assume that the positive half of the signed domain map to the bottom half of the unsigned domain.

But it also often assume that if a signed number reaches in the negative signed half it has no unsigned mapping while this is not true.
In fact the negative half of the signed domain perfectly maps to the top half of the unsigned domain.

The problem only exists at the discontinuity between maxint & minint.

In other words for always negative number int(x) < int(y) proves uint(x) < uint(y).

For one concrete example, applying the mathematical truth spelled out by the sentence above:

// signed <-> unsigned propagation
if lim.min >= 0 {
lim = lim.unsignedMinMax(uint64(lim.min), uint64(lim.max))
}
if fitsInBitsU(lim.umax, uint(8*v.Type.Size()-1)) {
lim = lim.signedMinMax(int64(lim.umin), int64(lim.umax))
}

The perfect* version of this code is:

	// signed <-> unsigned propagation
	bitsize := v.Type.Size()*8
	if sign(lim.min) == sign(lim.max) {
		lim = lim.unsignedMinMax(convertIntWithBitsize[uint64](lim.min, bitsize), convertIntWithBitsize[uint64](lim.max, bitsize))
	}
	intUmin, intUmax := convertIntWithBitsize[int64](lim.umin, bitsize), convertIntWithBitsize[int64](lim.umax, bitsize)
	if sign(intUmin) == sign(intUmax) {
		lim = lim.signedMinMax(intUmin, intUmax)
	}

*within the constraints of what limit can model.


I wished we wouldn't have to write workarounds like 03fcb33 does.
It shouldn't be too hard to fix because each occurrence of this "bug" since the current code is never wrong, but it is sometimes too conservative.
So each occurrence can be fixed in a vacuum.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions