(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
>;
+// Fold x op 1 -> x
+def right_identity_one: GICombineRule<
+ (defs root:$root),
+ (match (wip_match_opcode G_MUL):$root,
+ [{ return Helper.matchConstantOp(${root}->getOperand(2), 1); }]),
+ (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
+>;
+
// Fold (x op x) - > x
def binop_same_val: GICombineRule<
(defs root:$root),
(apply [{ return Helper.applyCombineTruncOfShl(*${root}, ${matchinfo}); }])
>;
+// Transform (mul x, -1) -> (sub 0, x)
+def mul_by_neg_one: GICombineRule <
+ (defs root:$root),
+ (match (wip_match_opcode G_MUL):$root,
+ [{ return Helper.matchConstantOp(${root}->getOperand(2), -1); }]),
+ (apply [{ return Helper.applyCombineMulByNegativeOne(*${root}); }])
+>;
+
// FIXME: These should use the custom predicate feature once it lands.
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
undef_to_negative_one,
binop_same_val, binop_left_to_zero,
binop_right_to_zero, p2i_to_i2p,
i2p_to_p2i, anyext_trunc_fold,
- fneg_fneg_fold]>;
+ fneg_fneg_fold, right_identity_one]>;
def known_bits_simplifications : GICombineGroup<[
and_trivial_mask, redundant_sext_inreg]>;
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp]>;
-def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd]>;
+def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
+ mul_by_neg_one]>;
+
def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
combines_for_extload, combine_indexed_load_store, undef_combines,
identity_combines, simplify_add_to_sub,
--- /dev/null
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
+
+---
+name: mul_by_zero
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK-LABEL: name: mul_by_zero
+ ; CHECK: liveins: $x0
+ ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+ ; CHECK: $x0 = COPY [[C]](s64)
+ %0:_(s64) = COPY $x0
+ %1:_(s64) = G_CONSTANT i64 0
+ %2:_(s64) = G_MUL %0, %1(s64)
+ $x0 = COPY %2(s64)
+...
+---
+name: mul_vector_by_zero
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.0:
+ liveins: $q0
+ ; Currently not implemented.
+ ; CHECK-LABEL: name: mul_vector_by_zero
+ ; CHECK: liveins: $q0
+ ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+ ; CHECK: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR]]
+ ; CHECK: $q0 = COPY [[MUL]](<4 x s32>)
+ %0:_(<4 x s32>) = COPY $q0
+ %1:_(s32) = G_CONSTANT i32 0
+ %2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
+ %3:_(<4 x s32>) = G_MUL %0, %2(<4 x s32>)
+ $q0 = COPY %3(<4 x s32>)
+...
+---
+name: mul_by_one
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK-LABEL: name: mul_by_one
+ ; CHECK: liveins: $x0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK: $x0 = COPY [[COPY]](s64)
+ %0:_(s64) = COPY $x0
+ %1:_(s64) = G_CONSTANT i64 1
+ %2:_(s64) = G_MUL %0, %1(s64)
+ $x0 = COPY %2(s64)
+...
+---
+name: mul_vector_by_one
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.0:
+ liveins: $q0
+ ; Currently not implemented.
+ ; CHECK-LABEL: name: mul_vector_by_one
+ ; CHECK: liveins: $q0
+ ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+ ; CHECK: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR]]
+ ; CHECK: $q0 = COPY [[MUL]](<4 x s32>)
+ %0:_(<4 x s32>) = COPY $q0
+ %1:_(s32) = G_CONSTANT i32 1
+ %2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
+ %3:_(<4 x s32>) = G_MUL %0, %2(<4 x s32>)
+ $q0 = COPY %3(<4 x s32>)
+...
+---
+name: mul_by_neg_one
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK-LABEL: name: mul_by_neg_one
+ ; CHECK: liveins: $x0
+ ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+ ; CHECK: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[C]], [[COPY]]
+ ; CHECK: $x0 = COPY [[SUB]](s64)
+ %0:_(s64) = COPY $x0
+ %1:_(s64) = G_CONSTANT i64 -1
+ %2:_(s64) = G_MUL %0, %1(s64)
+ $x0 = COPY %2(s64)
+...
+---
+name: mul_vector_by_neg_one
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.0:
+ liveins: $q0
+ ; Currently not implemented.
+ ; CHECK-LABEL: name: mul_vector_by_neg_one
+ ; CHECK: liveins: $q0
+ ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+ ; CHECK: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR]]
+ ; CHECK: $q0 = COPY [[MUL]](<4 x s32>)
+ %0:_(<4 x s32>) = COPY $q0
+ %1:_(s32) = G_CONSTANT i32 -1
+ %2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
+ %3:_(<4 x s32>) = G_MUL %0, %2(<4 x s32>)
+ $q0 = COPY %3(<4 x s32>)
+...