LoongArch: Remove undefined behavior from code [PR 106097]

C++2017 and previous standard description:

The value of E1 << E2 is E1 left-shifted E2 bit positions;
vacated bits are zero-filled. If E1 has an unsigned type,
the value of the result is E1×2E2, reduced modulo one more
than the maximum value representable inthe result type.
Otherwise, if E1 has a signed type and non-negative value,
and E1×2E2 is representablein the corresponding unsigned
type of the result type, then that value, converted to the
result type, is the resulting value; otherwise, the behavior
is undefined.

The value of E1 >> E2 is E1 right-shifted E2 bit positions.
If E1 has an unsigned type or if E1 has a signed type and
a non-negative value, the value of the result is the integral
part of the quotient of E1/2E2. If E1 has a signed type and
a negative value, the resulting value is implementation-defined.

gcc/ChangeLog:

	PR target/106097
	* config/loongarch/loongarch.cc (loongarch_build_integer):
	Remove undefined behavior from code.
This commit is contained in:
Lulu Cheng 2022-06-27 16:26:25 +08:00
parent b93ae1a01b
commit 43653547e7

View file

@ -160,7 +160,7 @@ enum loongarch_load_imm_method
struct loongarch_integer_op struct loongarch_integer_op
{ {
enum rtx_code code; enum rtx_code code;
unsigned HOST_WIDE_INT value; HOST_WIDE_INT value;
enum loongarch_load_imm_method method; enum loongarch_load_imm_method method;
}; };
@ -1468,7 +1468,7 @@ loongarch_build_integer (struct loongarch_integer_op *codes,
unsigned int cost = 0; unsigned int cost = 0;
/* Get the lower 32 bits of the value. */ /* Get the lower 32 bits of the value. */
HOST_WIDE_INT low_part = TARGET_64BIT ? value << 32 >> 32 : value; HOST_WIDE_INT low_part = (int32_t)value;
if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part)) if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part))
{ {
@ -1502,6 +1502,7 @@ loongarch_build_integer (struct loongarch_integer_op *codes,
bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B}; bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B};
int sign31 = (value & (1UL << 31)) >> 31; int sign31 = (value & (1UL << 31)) >> 31;
int sign51 = (value & (1UL << 51)) >> 51;
/* Determine whether the upper 32 bits are sign-extended from the lower /* Determine whether the upper 32 bits are sign-extended from the lower
32 bits. If it is, the instructions to load the high order can be 32 bits. If it is, the instructions to load the high order can be
ommitted. */ ommitted. */
@ -1512,12 +1513,12 @@ loongarch_build_integer (struct loongarch_integer_op *codes,
else if (lu32i[sign31]) else if (lu32i[sign31])
{ {
codes[cost].method = METHOD_LU52I; codes[cost].method = METHOD_LU52I;
codes[cost].value = (value >> 52) << 52; codes[cost].value = value & LU52I_B;
return cost + 1; return cost + 1;
} }
codes[cost].method = METHOD_LU32I; codes[cost].method = METHOD_LU32I;
codes[cost].value = ((value << 12) >> 44) << 32; codes[cost].value = (value & LU32I_B) | (sign51 ? LU52I_B : 0);
cost++; cost++;
/* Determine whether the 52-61 bits are sign-extended from the low order, /* Determine whether the 52-61 bits are sign-extended from the low order,
@ -1525,7 +1526,7 @@ loongarch_build_integer (struct loongarch_integer_op *codes,
if (!lu52i[(value & (1ULL << 51)) >> 51]) if (!lu52i[(value & (1ULL << 51)) >> 51])
{ {
codes[cost].method = METHOD_LU52I; codes[cost].method = METHOD_LU52I;
codes[cost].value = (value >> 52) << 52; codes[cost].value = value & LU52I_B;
cost++; cost++;
} }
} }