Implement shift-immediate encodings for x86 (#283)

* add x86 encodings for shift-immediate instructions

implements encodings for ishl_imm, sshr_imm, and ushr_imm. uses 8-bit immediates.

added tests for the encodings to intel/binary64.cton. Canonical versions
come from llvm-mc.

* translate test to use shift-immediates

* shift immediate encodings: use enc_i32_i64

and note why the regular shift encodings cant use it above

* add additional encoding tests for shift immediates

this covers 32 bit mode, and 64 bit operations in 64 bit mode.
This commit is contained in:
Pat Hickey
2018-03-26 16:48:20 -07:00
committed by Dan Gohman
parent 51eea8b89d
commit 80d2c5d9bf
6 changed files with 59 additions and 24 deletions

View File

@@ -47,28 +47,23 @@ ebb1(v20: i32):
function %i64_popcount(i64) -> i64 { function %i64_popcount(i64) -> i64 {
ebb0(v30: i64): ebb0(v30: i64):
v31 = popcnt v30; v31 = popcnt v30;
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: iconst.i64 ; check: iconst.i64
; check: band ; check: band
; check: isub ; check: isub
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: band ; check: band
; check: isub ; check: isub
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: band ; check: band
; check: isub ; check: isub
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: iadd ; check: iadd
; check: iconst.i64 ; check: iconst.i64
; check: band ; check: band
; check: iconst.i64 ; check: iconst.i64
; check: imul ; check: imul
; check: iconst.i32 ; check: ushr_imm
; check: ushr
return v31; return v31;
} }
@@ -78,27 +73,22 @@ ebb0(v30: i64):
function %i32_popcount(i32) -> i32 { function %i32_popcount(i32) -> i32 {
ebb0(v40: i32): ebb0(v40: i32):
v41 = popcnt v40; v41 = popcnt v40;
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: iconst.i32 ; check: iconst.i32
; check: band ; check: band
; check: isub ; check: isub
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: band ; check: band
; check: isub ; check: isub
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: band ; check: band
; check: isub ; check: isub
; check: iconst.i32 ; check: ushr_imm
; check: ushr
; check: iadd ; check: iadd
; check: iconst.i32 ; check: iconst.i32
; check: band ; check: band
; check: iconst.i32 ; check: iconst.i32
; check: imul ; check: imul
; check: iconst.i32 ; check: ushr_imm
; check: ushr
return v41; return v41;
} }

View File

@@ -403,6 +403,13 @@ ebb0:
; asm: addl $-2147483648, %esp ; asm: addl $-2147483648, %esp
adjust_sp_imm -2147483648 ; bin: 81 c4 80000000 adjust_sp_imm -2147483648 ; bin: 81 c4 80000000
; Shift immediates
; asm: shll $2, %esi
[-,%rsi] v513 = ishl_imm v2, 2 ; bin: c1 e6 02
; asm: sarl $5, %esi
[-,%rsi] v514 = sshr_imm v2, 5 ; bin: c1 fe 05
; asm: shrl $8, %esi
[-,%rsi] v515 = ushr_imm v2, 8 ; bin: c1 ee 08
; asm: testl %ecx, %ecx ; asm: testl %ecx, %ecx
; asm: je ebb1 ; asm: je ebb1

View File

@@ -529,6 +529,21 @@ ebb0:
; asm: addq $-2147483648, %rsp ; asm: addq $-2147483648, %rsp
adjust_sp_imm -2147483648 ; bin: 48 81 c4 80000000 adjust_sp_imm -2147483648 ; bin: 48 81 c4 80000000
; Shift immediates
; asm: shlq $12, %rsi
[-,%rsi] v515 = ishl_imm v2, 12 ; bin: 48 c1 e6 0c
; asm: shlq $13, %r8
[-,%r8] v516 = ishl_imm v4, 13 ; bin: 49 c1 e0 0d
; asm: sarq $32, %rsi
[-,%rsi] v517 = sshr_imm v2, 32 ; bin: 48 c1 fe 20
; asm: sarq $33, %r8
[-,%r8] v518 = sshr_imm v4, 33 ; bin: 49 c1 f8 21
; asm: shrl $62, %rsi
[-,%rsi] v519 = ushr_imm v2, 62 ; bin: 48 c1 ee 3e
; asm: shrl $63, %r8
[-,%r8] v520 = ushr_imm v4, 63 ; bin: 49 c1 e8 3f
; asm: testq %rcx, %rcx ; asm: testq %rcx, %rcx
; asm: je ebb1 ; asm: je ebb1
brz v1, ebb1 ; bin: 48 85 c9 74 1b brz v1, ebb1 ; bin: 48 85 c9 74 1b
@@ -653,6 +668,7 @@ ebb1:
; asm: cmpq $10000, %r10 ; asm: cmpq $10000, %r10
[-,%eflags] v525 = ifcmp_imm v2, 10000 ; bin: 49 81 fa 00002710 [-,%eflags] v525 = ifcmp_imm v2, 10000 ; bin: 49 81 fa 00002710
return return
} }
@@ -1053,6 +1069,19 @@ ebb0:
; asm: cmpl $10000, %r10d ; asm: cmpl $10000, %r10d
[-,%eflags] v525 = ifcmp_imm v3, 10000 ; bin: 41 81 fa 00002710 [-,%eflags] v525 = ifcmp_imm v3, 10000 ; bin: 41 81 fa 00002710
; asm: shll $2, %esi
[-,%rsi] v526 = ishl_imm v2, 2 ; bin: c1 e6 02
; asm: shll $12, %r10d
[-,%r10] v527 = ishl_imm v3, 12 ; bin: 41 c1 e2 0c
; asm: sarl $5, %esi
[-,%rsi] v529 = sshr_imm v2, 5 ; bin: c1 fe 05
; asm: sarl $32, %r10d
[-,%r10] v530 = sshr_imm v3, 32 ; bin: 41 c1 fa 20
; asm: shrl $8, %esi
[-,%rsi] v532 = ushr_imm v2, 8 ; bin: c1 ee 08
; asm: shrl $31, %r10d
[-,%r10] v533 = ushr_imm v3, 31 ; bin: 41 c1 ea 1f
; asm: testl %ecx, %ecx ; asm: testl %ecx, %ecx
; asm: je ebb1x ; asm: je ebb1x
brz v1, ebb1 ; bin: 85 c9 74 18 brz v1, ebb1 ; bin: 85 c9 74 18
@@ -1082,6 +1111,7 @@ ebb1:
; asm: ebb2x: ; asm: ebb2x:
ebb2: ebb2:
jump ebb1 ; bin: eb fd jump ebb1 ; bin: eb fd
} }
; Tests for i32/i8 conversion instructions. ; Tests for i32/i8 conversion instructions.

View File

@@ -40,7 +40,7 @@ ebb0(v0: i64, v1: i64):
; nextln: brif eq $fm1, $(m1=$EBB) ; nextln: brif eq $fm1, $(m1=$EBB)
; nextln: $(fz=$V) = ifcmp_imm v1, 0 ; nextln: $(fz=$V) = ifcmp_imm v1, 0
; nextln: trapif eq $fz, int_divz ; nextln: trapif eq $fz, int_divz
; check: $(hi=$V) = sshr ; check: $(hi=$V) = sshr_imm
; nextln: $(q=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: $(q=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1
; nextln: jump $(done=$EBB)($q) ; nextln: jump $(done=$EBB)($q)
; check: $m1: ; check: $m1:
@@ -60,7 +60,7 @@ ebb0(v0: i64, v1: i64):
v2 = srem v0, v1 v2 = srem v0, v1
; nextln: $(fm1=$V) = ifcmp_imm v1, -1 ; nextln: $(fm1=$V) = ifcmp_imm v1, -1
; nextln: brif eq $fm1, $(m1=$EBB) ; nextln: brif eq $fm1, $(m1=$EBB)
; check: $(hi=$V) = sshr ; check: $(hi=$V) = sshr_imm
; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1
; nextln: jump $(done=$EBB)($r) ; nextln: jump $(done=$EBB)($r)
; check: $m1: ; check: $m1:

View File

@@ -32,7 +32,7 @@ function %sdiv(i64, i64) -> i64 {
ebb0(v0: i64, v1: i64): ebb0(v0: i64, v1: i64):
; check: ebb0( ; check: ebb0(
v2 = sdiv v0, v1 v2 = sdiv v0, v1
; check: $(hi=$V) = sshr ; check: $(hi=$V) = sshr_imm
; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1
return v2 return v2
; nextln: return $d ; nextln: return $d
@@ -46,7 +46,7 @@ ebb0(v0: i64, v1: i64):
v2 = srem v0, v1 v2 = srem v0, v1
; nextln: $(fm1=$V) = ifcmp_imm v1, -1 ; nextln: $(fm1=$V) = ifcmp_imm v1, -1
; nextln: brif eq $fm1, $(m1=$EBB) ; nextln: brif eq $fm1, $(m1=$EBB)
; check: $(hi=$V) = sshr ; check: $(hi=$V) = sshr_imm
; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1 ; nextln: $(d=$V), $(r=$V) = x86_sdivmodx v0, $hi, v1
; nextln: jump $(done=$EBB)($r) ; nextln: jump $(done=$EBB)($r)
; check: $m1: ; check: $m1:

View File

@@ -164,11 +164,19 @@ for inst, rrr in [
(base.ishl, 4), (base.ishl, 4),
(base.ushr, 5), (base.ushr, 5),
(base.sshr, 7)]: (base.sshr, 7)]:
# Cannot use enc_i32_i64 for this pattern because instructions require
# .any suffix.
X86_32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) X86_32.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr))
X86_64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1)) X86_64.enc(inst.i64.any, *r.rc.rex(0xd3, rrr=rrr, w=1))
X86_64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr)) X86_64.enc(inst.i32.any, *r.rc.rex(0xd3, rrr=rrr))
X86_64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr)) X86_64.enc(inst.i32.any, *r.rc(0xd3, rrr=rrr))
for inst, rrr in [
(base.ishl_imm, 4),
(base.ushr_imm, 5),
(base.sshr_imm, 7)]:
enc_i32_i64(inst, r.rib, 0xc1, rrr=rrr)
# Population count. # Population count.
X86_32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt) X86_32.enc(base.popcnt.i32, *r.urm(0xf3, 0x0f, 0xb8), isap=cfg.use_popcnt)
X86_64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1), X86_64.enc(base.popcnt.i64, *r.urm.rex(0xf3, 0x0f, 0xb8, w=1),