Skip to content

Commit

Permalink
[GlobalISel] Add a constant folding combine.
Browse files Browse the repository at this point in the history
Use it AArch64 post-legal combiner. These don't always get folded because when
the instructions are created the constants are obscured by artifacts.

Differential Revision: https://reviews.llvm.org/D106776
  • Loading branch information
aemerson committed Jul 26, 2021
1 parent a48ee9f commit c658b47
Show file tree
Hide file tree
Showing 13 changed files with 2,651 additions and 2,786 deletions.
7 changes: 7 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ class CombinerHelper {
/// Replace an instruction with a G_CONSTANT with value \p C.
bool replaceInstWithConstant(MachineInstr &MI, int64_t C);

/// Replace an instruction with a G_CONSTANT with value \p C.
bool replaceInstWithConstant(MachineInstr &MI, APInt C);

/// Replace an instruction with a G_IMPLICIT_DEF.
bool replaceInstWithUndef(MachineInstr &MI);

Expand Down Expand Up @@ -543,6 +546,10 @@ class CombinerHelper {
bool matchReassocPtrAdd(MachineInstr &MI,
std::function<void(MachineIRBuilder &)> &MatchInfo);


/// Do constant folding when opportunities are exposed after MIR building.
bool matchConstantFold(MachineInstr &MI, APInt &MatchInfo);

/// Try to transform \p MI by using all of the above
/// combine functions. Returns true if changed.
bool tryCombine(MachineInstr &MI);
Expand Down
11 changes: 10 additions & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class GIApplyKindWithArgs;

def register_matchinfo: GIDefMatchData<"Register">;
def int64_matchinfo: GIDefMatchData<"int64_t">;
def apint_matchinfo : GIDefMatchData<"APInt">;
def build_fn_matchinfo :
GIDefMatchData<"std::function<void(MachineIRBuilder &)>">;

Expand Down Expand Up @@ -661,6 +662,13 @@ def reassoc_ptradd : GICombineRule<

def reassocs : GICombineGroup<[reassoc_ptradd]>;

// Constant fold operations.
def constant_fold : GICombineRule<
(defs root:$d, apint_matchinfo:$matchinfo),
(match (wip_match_opcode G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR):$d,
[{ return Helper.matchConstantFold(*${d}, ${matchinfo}); }]),
(apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>;

// 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,
Expand Down Expand Up @@ -705,7 +713,8 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
unmerge_zext_to_zext, merge_unmerge, trunc_ext_fold, trunc_shl,
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
div_rem_to_divrem, funnel_shift_combines, form_bitfield_extract]>;
div_rem_to_divrem, funnel_shift_combines, form_bitfield_extract,
constant_fold]>;

// A combine group used to for prelegalizer combiners at -O0. The combines in
// this group have been selected based on experiments to balance code size and
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,14 @@ bool CombinerHelper::replaceInstWithConstant(MachineInstr &MI, int64_t C) {
return true;
}

bool CombinerHelper::replaceInstWithConstant(MachineInstr &MI, APInt C) {
assert(MI.getNumDefs() == 1 && "Expected only one def?");
Builder.setInstr(MI);
Builder.buildConstant(MI.getOperand(0), C);
MI.eraseFromParent();
return true;
}

bool CombinerHelper::replaceInstWithUndef(MachineInstr &MI) {
assert(MI.getNumDefs() == 1 && "Expected only one def?");
Builder.setInstr(MI);
Expand Down Expand Up @@ -4246,6 +4254,16 @@ bool CombinerHelper::matchReassocPtrAdd(
return !reassociationCanBreakAddressingModePattern(MI);
}

bool CombinerHelper::matchConstantFold(MachineInstr &MI, APInt &MatchInfo) {
Register Op1 = MI.getOperand(1).getReg();
Register Op2 = MI.getOperand(2).getReg();
auto MaybeCst = ConstantFoldBinOp(MI.getOpcode(), Op1, Op2, MRI);
if (!MaybeCst)
return false;
MatchInfo = *MaybeCst;
return true;
}

bool CombinerHelper::tryCombine(MachineInstr &MI) {
if (tryCombineCopy(MI))
return true;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ def AArch64PostLegalizerCombinerHelper
mul_const, redundant_sext_inreg,
form_bitfield_extract, rotate_out_of_range,
icmp_to_true_false_known_bits, merge_unmerge,
select_combines, fold_merge_to_zext]> {
select_combines, fold_merge_to_zext,
constant_fold]> {
let DisableRuleOption = "aarch64postlegalizercombiner-disable-rule";
}
28 changes: 12 additions & 16 deletions llvm/test/CodeGen/AArch64/GlobalISel/arm64-atomic-128.ll
Original file line number Diff line number Diff line change
Expand Up @@ -347,34 +347,30 @@ define void @val_compare_and_swap_monotonic(i128* %p, i128 %oldval, i128 %newval
define void @atomic_load_relaxed(i64, i64, i128* %p, i128* %p2) {
; CHECK-LLSC-O1-LABEL: atomic_load_relaxed:
; CHECK-LLSC-O1: // %bb.0:
; CHECK-LLSC-O1-NEXT: mov w8, #64
; CHECK-LLSC-O1-NEXT: sub x9, x8, #64 // =64
; CHECK-LLSC-O1-NEXT: .LBB4_1: // %atomicrmw.start
; CHECK-LLSC-O1-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-LLSC-O1-NEXT: ldxp x10, x8, [x2]
; CHECK-LLSC-O1-NEXT: lsl x8, x8, x9
; CHECK-LLSC-O1-NEXT: lsr x11, x8, x9
; CHECK-LLSC-O1-NEXT: stxp w12, x10, x11, [x2]
; CHECK-LLSC-O1-NEXT: cbnz w12, .LBB4_1
; CHECK-LLSC-O1-NEXT: ldxp x9, x8, [x2]
; CHECK-LLSC-O1-NEXT: lsr x8, x8, #0
; CHECK-LLSC-O1-NEXT: lsr x10, x8, #0
; CHECK-LLSC-O1-NEXT: stxp w11, x9, x10, [x2]
; CHECK-LLSC-O1-NEXT: cbnz w11, .LBB4_1
; CHECK-LLSC-O1-NEXT: // %bb.2: // %atomicrmw.end
; CHECK-LLSC-O1-NEXT: mov v0.d[0], x10
; CHECK-LLSC-O1-NEXT: mov v0.d[0], x9
; CHECK-LLSC-O1-NEXT: mov v0.d[1], x8
; CHECK-LLSC-O1-NEXT: str q0, [x3]
; CHECK-LLSC-O1-NEXT: ret
;
; CHECK-CAS-O1-LABEL: atomic_load_relaxed:
; CHECK-CAS-O1: // %bb.0:
; CHECK-CAS-O1-NEXT: mov w8, #64
; CHECK-CAS-O1-NEXT: sub x9, x8, #64 // =64
; CHECK-CAS-O1-NEXT: .LBB4_1: // %atomicrmw.start
; CHECK-CAS-O1-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-CAS-O1-NEXT: ldxp x10, x8, [x2]
; CHECK-CAS-O1-NEXT: lsl x8, x8, x9
; CHECK-CAS-O1-NEXT: lsr x11, x8, x9
; CHECK-CAS-O1-NEXT: stxp w12, x10, x11, [x2]
; CHECK-CAS-O1-NEXT: cbnz w12, .LBB4_1
; CHECK-CAS-O1-NEXT: ldxp x9, x8, [x2]
; CHECK-CAS-O1-NEXT: lsr x8, x8, #0
; CHECK-CAS-O1-NEXT: lsr x10, x8, #0
; CHECK-CAS-O1-NEXT: stxp w11, x9, x10, [x2]
; CHECK-CAS-O1-NEXT: cbnz w11, .LBB4_1
; CHECK-CAS-O1-NEXT: // %bb.2: // %atomicrmw.end
; CHECK-CAS-O1-NEXT: mov v0.d[0], x10
; CHECK-CAS-O1-NEXT: mov v0.d[0], x9
; CHECK-CAS-O1-NEXT: mov v0.d[1], x8
; CHECK-CAS-O1-NEXT: str q0, [x3]
; CHECK-CAS-O1-NEXT: ret
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s

---
name: add
alignment: 4
legalized: true
liveins:
- { reg: '$w0' }
body: |
bb.1.entry:
liveins: $x0
; CHECK-LABEL: name: add
; CHECK: %res:_(s64) = G_CONSTANT i64 42
; CHECK: $x0 = COPY %res(s64)
; CHECK: RET_ReallyLR implicit $x0
%a:_(s64) = G_CONSTANT i64 40
%b:_(s64) = G_CONSTANT i64 2
%res:_(s64) = G_ADD %a, %b
$x0 = COPY %res(s64)
RET_ReallyLR implicit $x0
...
---
name: sub
alignment: 4
legalized: true
liveins:
- { reg: '$w0' }
body: |
bb.1.entry:
liveins: $x0
; CHECK-LABEL: name: sub
; CHECK: %res:_(s64) = G_CONSTANT i64 38
; CHECK: $x0 = COPY %res(s64)
; CHECK: RET_ReallyLR implicit $x0
%a:_(s64) = G_CONSTANT i64 40
%b:_(s64) = G_CONSTANT i64 2
%res:_(s64) = G_SUB %a, %b
$x0 = COPY %res(s64)
RET_ReallyLR implicit $x0
...
---
name: mul
alignment: 4
legalized: true
liveins:
- { reg: '$w0' }
body: |
bb.1.entry:
liveins: $x0
; CHECK-LABEL: name: mul
; CHECK: %res:_(s64) = G_CONSTANT i64 80
; CHECK: $x0 = COPY %res(s64)
; CHECK: RET_ReallyLR implicit $x0
%a:_(s64) = G_CONSTANT i64 40
%b:_(s64) = G_CONSTANT i64 2
%res:_(s64) = G_MUL %a, %b
$x0 = COPY %res(s64)
RET_ReallyLR implicit $x0
...
---
name: and
alignment: 4
legalized: true
liveins:
- { reg: '$w0' }
body: |
bb.1.entry:
liveins: $x0
; CHECK-LABEL: name: and
; CHECK: %res:_(s64) = G_CONSTANT i64 0
; CHECK: $x0 = COPY %res(s64)
; CHECK: RET_ReallyLR implicit $x0
%a:_(s64) = G_CONSTANT i64 40
%b:_(s64) = G_CONSTANT i64 2
%res:_(s64) = G_AND %a, %b
$x0 = COPY %res(s64)
RET_ReallyLR implicit $x0
...
---
name: or
alignment: 4
legalized: true
liveins:
- { reg: '$w0' }
body: |
bb.1.entry:
liveins: $x0
; CHECK-LABEL: name: or
; CHECK: %res:_(s64) = G_CONSTANT i64 62
; CHECK: $x0 = COPY %res(s64)
; CHECK: RET_ReallyLR implicit $x0
%a:_(s64) = G_CONSTANT i64 42
%b:_(s64) = G_CONSTANT i64 22
%res:_(s64) = G_OR %a, %b
$x0 = COPY %res(s64)
RET_ReallyLR implicit $x0
...
---
name: xor
alignment: 4
legalized: true
liveins:
- { reg: '$w0' }
body: |
bb.1.entry:
liveins: $x0
; CHECK-LABEL: name: xor
; CHECK: %res:_(s64) = G_CONSTANT i64 12
; CHECK: $x0 = COPY %res(s64)
; CHECK: RET_ReallyLR implicit $x0
%a:_(s64) = G_CONSTANT i64 8
%b:_(s64) = G_CONSTANT i64 4
%res:_(s64) = G_XOR %a, %b
$x0 = COPY %res(s64)
RET_ReallyLR implicit $x0
...
6 changes: 2 additions & 4 deletions llvm/test/CodeGen/AArch64/fold-global-offsets.ll
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,9 @@ define i32 @f7() {
; GISEL-NEXT: adrp x8, x3+88
; GISEL-NEXT: add x8, x8, :lo12:x3+88
; GISEL-NEXT: mov v0.d[1], x8
; GISEL-NEXT: mov w9, #64
; GISEL-NEXT: mov d0, v0.d[1]
; GISEL-NEXT: sub x8, x9, #64 // =64
; GISEL-NEXT: fmov x9, d0
; GISEL-NEXT: lsr x8, x9, x8
; GISEL-NEXT: fmov x8, d0
; GISEL-NEXT: lsr x8, x8, #0
; GISEL-NEXT: ldr w0, [x8, #20]
; GISEL-NEXT: ret

Expand Down
Loading

0 comments on commit c658b47

Please sign in to comment.