Skip to content

Commit 452545c

Browse files
committed
Detect the special case for ISHFT for int8
When we convert int to signed short int, we first do a sign extension, and then left shift 24 bits, followed by arithmetic right shift 24 bits (filled with sign bits), then followed by the real ishft, then truncate to int8. Therefore the logical left shift never happened to int8. The fix is to recognize the special case for ISHFT on a short int, and do a logical shift instead of an arithmetic shift.
1 parent efb385e commit 452545c

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

tools/flang2/flang2exe/exp_ftn.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ static int accreduct_op;
8383

8484
#define mk_prototype mk_prototype_llvm
8585

86+
bool ishft = false;
87+
8688
static int
8789
forceK(int ili)
8890
{
@@ -124,6 +126,32 @@ double_is_small_int(int ilix)
124126
return ret_ili;
125127
}
126128

129+
/**
130+
* \brief check special case for ISHFT(int8)
131+
*/
132+
static bool
133+
is_ishft(int curilm)
134+
{
135+
ILM *ilmp;
136+
ILM_OP opc;
137+
int len, bsize, ilmx;
138+
len = 0;
139+
bsize = ilmb.ilm_base[BOS_SIZE - 1];
140+
ilmx = 0;
141+
do {
142+
ilmx += len;
143+
ilmp = (ILM *)(ilmb.ilm_base + curilm + ilmx);
144+
opc = ILM_OPC(ilmp);
145+
len = ilms[opc].oprs + 1;
146+
if (IM_VAR(opc))
147+
len += ILM_OPND(ilmp, 1);
148+
if (opc == IM_JISHFT && (ILM_OPND(ilmp, 1) == curilm)) {
149+
return true;
150+
}
151+
} while (curilm + ilmx + len < bsize);
152+
return false;
153+
}
154+
127155
void
128156
exp_ac(ILM_OP opc, ILM *ilmp, int curilm)
129157
{
@@ -364,7 +392,14 @@ exp_ac(ILM_OP opc, ILM *ilmp, int curilm)
364392
val[1] <<= 3; /* difference in bits */
365393
op2 = ad_icon(val[1]);
366394
tmp = ad2ili(IL_LSHIFT, op1, op2);
367-
op1 = ad2ili(IL_ARSHIFT, tmp, op2);
395+
if (is_ishft(curilm)) {
396+
/* Special case for ishft(int8) */
397+
ishft = true;
398+
op1 = ad2ili(IL_URSHIFT, tmp, op2);
399+
ishft = false;
400+
} else {
401+
op1 = ad2ili(IL_ARSHIFT, tmp, op2);
402+
}
368403
}
369404
ILM_RESULT(curilm) = op1;
370405
return;

tools/flang2/flang2exe/iliutil.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ union ATOMIC_ENCODER {
6868

6969
bool share_proc_ili = false;
7070
bool share_qjsr_ili = false;
71+
extern bool ishft;
7172

7273
static int addarth(ILI *);
7374
static int red_iadd(int, INT);
@@ -5350,7 +5351,11 @@ addarth(ILI *ilip)
53505351
} else if (ncons == 3) {
53515352
tmp = con2v2;
53525353
if (SHIFTOK(tmp)) {
5353-
res.numi[1] = URSHIFT(con1v2, tmp);
5354+
if (ishft) {
5355+
res.numi[1] = ARSHIFT(con1v2, tmp);
5356+
} else {
5357+
res.numi[1] = URSHIFT(con1v2, tmp);
5358+
}
53545359
goto add_icon;
53555360
}
53565361
}

0 commit comments

Comments
 (0)