Merge pull request #2051 from cfallin/aarch64-add-negative-imm
Aarch64 codegen quality: handle add-negative-imm as subtract.
This commit is contained in:
@@ -424,6 +424,35 @@ pub(crate) fn put_input_in_rse_imm12<C: LowerCtx<I = Inst>>(
|
|||||||
ResultRSEImm12::from_rse(put_input_in_rse(ctx, input, narrow_mode))
|
ResultRSEImm12::from_rse(put_input_in_rse(ctx, input, narrow_mode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `put_input_in_rse_imm12` above, except is allowed to negate the
|
||||||
|
/// argument (assuming a two's-complement representation with the given bit
|
||||||
|
/// width) if this allows use of 12-bit immediate. Used to flip `add`s with
|
||||||
|
/// negative immediates to `sub`s (and vice-versa).
|
||||||
|
pub(crate) fn put_input_in_rse_imm12_maybe_negated<C: LowerCtx<I = Inst>>(
|
||||||
|
ctx: &mut C,
|
||||||
|
input: InsnInput,
|
||||||
|
twos_complement_bits: usize,
|
||||||
|
narrow_mode: NarrowValueMode,
|
||||||
|
) -> (ResultRSEImm12, bool) {
|
||||||
|
assert!(twos_complement_bits <= 64);
|
||||||
|
if let Some(imm_value) = input_to_const(ctx, input) {
|
||||||
|
if let Some(i) = Imm12::maybe_from_u64(imm_value) {
|
||||||
|
return (ResultRSEImm12::Imm12(i), false);
|
||||||
|
}
|
||||||
|
let sign_extended =
|
||||||
|
((imm_value as i64) << (64 - twos_complement_bits)) >> (64 - twos_complement_bits);
|
||||||
|
let inverted = sign_extended.wrapping_neg();
|
||||||
|
if let Some(i) = Imm12::maybe_from_u64(inverted as u64) {
|
||||||
|
return (ResultRSEImm12::Imm12(i), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
ResultRSEImm12::from_rse(put_input_in_rse(ctx, input, narrow_mode)),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn put_input_in_rs_immlogic<C: LowerCtx<I = Inst>>(
|
pub(crate) fn put_input_in_rs_immlogic<C: LowerCtx<I = Inst>>(
|
||||||
ctx: &mut C,
|
ctx: &mut C,
|
||||||
input: InsnInput,
|
input: InsnInput,
|
||||||
|
|||||||
@@ -60,8 +60,17 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
||||||
let ty = ty.unwrap();
|
let ty = ty.unwrap();
|
||||||
if ty_bits(ty) < 128 {
|
if ty_bits(ty) < 128 {
|
||||||
let rm = put_input_in_rse_imm12(ctx, inputs[1], NarrowValueMode::None);
|
let (rm, negated) = put_input_in_rse_imm12_maybe_negated(
|
||||||
let alu_op = choose_32_64(ty, ALUOp::Add32, ALUOp::Add64);
|
ctx,
|
||||||
|
inputs[1],
|
||||||
|
ty_bits(ty),
|
||||||
|
NarrowValueMode::None,
|
||||||
|
);
|
||||||
|
let alu_op = if !negated {
|
||||||
|
choose_32_64(ty, ALUOp::Add32, ALUOp::Add64)
|
||||||
|
} else {
|
||||||
|
choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64)
|
||||||
|
};
|
||||||
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
|
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
|
||||||
} else {
|
} else {
|
||||||
let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||||
@@ -79,8 +88,17 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None);
|
||||||
let ty = ty.unwrap();
|
let ty = ty.unwrap();
|
||||||
if ty_bits(ty) < 128 {
|
if ty_bits(ty) < 128 {
|
||||||
let rm = put_input_in_rse_imm12(ctx, inputs[1], NarrowValueMode::None);
|
let (rm, negated) = put_input_in_rse_imm12_maybe_negated(
|
||||||
let alu_op = choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64);
|
ctx,
|
||||||
|
inputs[1],
|
||||||
|
ty_bits(ty),
|
||||||
|
NarrowValueMode::None,
|
||||||
|
);
|
||||||
|
let alu_op = if !negated {
|
||||||
|
choose_32_64(ty, ALUOp::Sub32, ALUOp::Sub64)
|
||||||
|
} else {
|
||||||
|
choose_32_64(ty, ALUOp::Add32, ALUOp::Add64)
|
||||||
|
};
|
||||||
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
|
ctx.emit(alu_inst_imm12(alu_op, rd, rn, rm));
|
||||||
} else {
|
} else {
|
||||||
let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
let rm = put_input_in_reg(ctx, inputs[1], NarrowValueMode::None);
|
||||||
|
|||||||
@@ -380,3 +380,45 @@ block0(v0: i32, v1: i32):
|
|||||||
; nextln: mov sp, fp
|
; nextln: mov sp, fp
|
||||||
; nextln: ldp fp, lr, [sp], #16
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
; nextln: ret
|
; nextln: ret
|
||||||
|
|
||||||
|
function %f26(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 -1
|
||||||
|
v2 = iadd.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; nextln: mov fp, sp
|
||||||
|
; nextln: sub w0, w0, #1
|
||||||
|
; nextln: mov sp, fp
|
||||||
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
|
; nextln: ret
|
||||||
|
|
||||||
|
function %f27(i32) -> i32 {
|
||||||
|
block0(v0: i32):
|
||||||
|
v1 = iconst.i32 -1
|
||||||
|
v2 = isub.i32 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; nextln: mov fp, sp
|
||||||
|
; nextln: add w0, w0, #1
|
||||||
|
; nextln: mov sp, fp
|
||||||
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
|
; nextln: ret
|
||||||
|
|
||||||
|
function %f28(i64) -> i64 {
|
||||||
|
block0(v0: i64):
|
||||||
|
v1 = iconst.i64 -1
|
||||||
|
v2 = isub.i64 v0, v1
|
||||||
|
return v2
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; nextln: mov fp, sp
|
||||||
|
; nextln: add x0, x0, #1
|
||||||
|
; nextln: mov sp, fp
|
||||||
|
; nextln: ldp fp, lr, [sp], #16
|
||||||
|
; nextln: ret
|
||||||
|
|||||||
Reference in New Issue
Block a user