Encode iconst.i32 for RISC-V.

For large constants with the low 12 bits clear, we already have the
"lui" encoding. Add "addi %x0" encodings for signed 12-bit constants.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-22 12:11:54 -07:00
parent e83e2ccf17
commit 9e02b9818f
5 changed files with 27 additions and 2 deletions

View File

@@ -77,6 +77,9 @@ ebb0(v9999: i32):
; lui
[-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7
[-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837
; addi
[-,%x7] v142 = iconst.i32 1000 ; bin: 3e800393
[-,%x16] v143 = iconst.i32 -905 ; bin: c7700813
; Copies alias to iadd_imm.
[-,%x7] v150 = copy v1 ; bin: 00050393

View File

@@ -6,7 +6,7 @@ function %RV32I(i32 link [%x1]) -> i32 link [%x1] {
ebb0(v9999: i32):
; iconst.i32 needs legalizing, so it should throw a
[R#0,-] v1 = iconst.i32 1 ; error: Instruction failed to re-encode
[R#0,-] v1 = iconst.i32 0xf0f0f0f0f0 ; error: Instruction failed to re-encode
return v9999
}

View File

@@ -7,7 +7,7 @@ from base.immediates import intcc
from .defs import RV32, RV64
from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH, JALR, JAL
from .recipes import LOAD, STORE
from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret, Icall, Icopy
from .recipes import R, Rshamt, Ricmp, I, Iz, Iicmp, Iret, Icall, Icopy
from .recipes import U, UJ, UJcall, SB, SBzero, GPsp, GPfi
from .settings import use_m
from cdsl.ast import Var
@@ -40,6 +40,11 @@ RV64.enc(base.isub.i32, R, OP32(0b000, 0b0100000))
# There are no andiw/oriw/xoriw variations.
RV64.enc(base.iadd_imm.i32, I, OPIMM32(0b000))
# Use iadd_imm with %x0 to materialize constants.
RV32.enc(base.iconst.i32, Iz, OPIMM(0b000))
RV64.enc(base.iconst.i32, Iz, OPIMM(0b000))
RV64.enc(base.iconst.i64, Iz, OPIMM(0b000))
# Dynamic shifts have the same masking semantics as the cton base instructions.
for inst, inst_imm, f3, f7 in [
(base.ishl, base.ishl_imm, 0b001, 0b0000000),

View File

@@ -104,6 +104,11 @@ I = EncRecipe(
'I', BinaryImm, size=4, ins=GPR, outs=GPR,
instp=IsSignedInt(BinaryImm.imm, 12))
# I-type instruction with a hardcoded %x0 rs1.
Iz = EncRecipe(
'Iz', UnaryImm, size=4, ins=(), outs=GPR,
instp=IsSignedInt(UnaryImm.imm, 12))
# I-type encoding of an integer comparison.
Iicmp = EncRecipe(
'Iicmp', IntCompareImm, size=4, ins=GPR, outs=GPR,

View File

@@ -160,6 +160,18 @@ fn recipe_i<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
}
}
fn recipe_iz<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::UnaryImm { imm, .. } = func.dfg[inst] {
put_i(func.encodings[inst].bits(),
0,
imm.into(),
func.locations[func.dfg.first_result(inst)].unwrap_reg(),
sink);
} else {
panic!("Expected UnaryImm format: {:?}", func.dfg[inst]);
}
}
fn recipe_iicmp<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::IntCompareImm { arg, imm, .. } = func.dfg[inst] {
put_i(func.encodings[inst].bits(),