diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -386,12 +386,6 @@ void applyCombineExtOfExt(MachineInstr &MI, std::tuple &MatchInfo); - /// Transform fabs(fabs(x)) to fabs(x). - void applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src); - - /// Transform fabs(fneg(x)) to fabs(x). - bool matchCombineFAbsOfFNeg(MachineInstr &MI, BuildFnTy &MatchInfo); - /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x). bool matchCombineTruncOfExt(MachineInstr &MI, std::pair &MatchInfo); diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -358,10 +358,10 @@ // Fold (undef ? x : y) -> y def select_undef_cmp: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SELECT):$root, - [{ return Helper.matchUndefSelectCmp(*${root}); }]), - (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) + (defs root:$dst), + (match (G_IMPLICIT_DEF $undef), + (G_SELECT $dst, $undef, $x, $y)), + (apply (COPY $dst, $y)) >; // Fold (true ? x : y) -> x @@ -400,28 +400,37 @@ >; // Fold x op 0 -> x +def right_identity_zero_frags : GICombinePatFrag< + (outs root:$dst), (ins $x), + !foreach(op, + [G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, + G_LSHR, G_PTR_ADD, G_ROTL, G_ROTR], + (pattern (op $dst, $x, 0)))>; def right_identity_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR, - G_PTR_ADD, G_ROTL, G_ROTR):$root, - [{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]), - (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) + (defs root:$dst), + (match (right_identity_zero_frags $dst, $lhs)), + (apply (COPY $dst, $lhs)) >; // 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 [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) + (defs root:$dst), + (match (G_MUL $dst, $x, 1)), + (apply (COPY $dst, $x)) >; // Fold (x op x) - > x +def binop_same_val_frags : GICombinePatFrag< + (outs root:$dst), (ins $x), + [ + (pattern (G_AND $dst, $x, $x)), + (pattern (G_OR $dst, $x, $x)), + ] +>; def binop_same_val: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_AND, G_OR):$root, - [{ return Helper.matchBinOpSameVal(*${root}); }]), - (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) + (defs root:$dst), + (match (binop_same_val_frags $dst, $src)), + (apply (COPY $dst, $src)) >; // Fold (0 op x) - > 0 @@ -470,10 +479,9 @@ // Fold (x op 0) - > 0 def binop_right_to_zero: GICombineRule< - (defs root:$root), - (match (wip_match_opcode G_MUL):$root, - [{ return Helper.matchOperandIsZero(*${root}, 2); }]), - (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) + (defs root:$dst), + (match (G_MUL $dst, $lhs, 0:$zero)), + (apply (COPY $dst, $zero)) >; // Erase stores of undef values. @@ -637,11 +645,10 @@ // Fold (fneg (fneg x)) -> x. def fneg_fneg_fold: GICombineRule < - (defs root:$dst, register_matchinfo:$matchinfo), + (defs root:$dst), (match (G_FNEG $t, $src), - (G_FNEG $dst, $t):$mi, - [{ ${matchinfo} = ${src}.getReg(); return true; }]), - (apply [{ Helper.replaceSingleDefInstWithReg(*${mi}, ${matchinfo}); }]) + (G_FNEG $dst, $t)), + (apply (COPY $dst, $src)) >; // Fold (unmerge(merge x, y, z)) -> z, y, z. @@ -663,10 +670,10 @@ // Fold (fabs (fneg x)) -> (fabs x). def fabs_fneg_fold: GICombineRule < - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_FABS):$root, - [{ return Helper.matchCombineFAbsOfFNeg(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; + (defs root:$dst), + (match (G_FNEG $tmp, $x), + (G_FABS $dst, $tmp)), + (apply (G_FABS $dst, $x))>; // Fold (unmerge cst) -> cst1, cst2, ... def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector">; @@ -1036,12 +1043,16 @@ // Transform (add x, (sub y, x)) -> y // Transform (add (sub y, x), x) -> y +def add_sub_reg_frags : GICombinePatFrag< + (outs root:$dst), (ins $src), + [ + (pattern (G_ADD $dst, $x, $tmp), (G_SUB $tmp, $src, $x)), + (pattern (G_ADD $dst, $tmp, $x), (G_SUB $tmp, $src, $x)) + ]>; def add_sub_reg: GICombineRule < - (defs root:$root, register_matchinfo:$matchinfo), - (match (wip_match_opcode G_ADD):$root, - [{ return Helper.matchAddSubSameReg(*${root}, ${matchinfo}); }]), - (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, - ${matchinfo}); }])>; + (defs root:$dst), + (match (add_sub_reg_frags $dst, $src)), + (apply (COPY $dst, $src))>; def buildvector_identity_fold : GICombineRule< (defs root:$build_vector, register_matchinfo:$matchinfo), diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -2260,23 +2260,6 @@ MI.eraseFromParent(); } -bool CombinerHelper::matchCombineFAbsOfFNeg(MachineInstr &MI, - BuildFnTy &MatchInfo) { - assert(MI.getOpcode() == TargetOpcode::G_FABS && "Expected a G_FABS"); - Register Src = MI.getOperand(1).getReg(); - Register NegSrc; - - if (!mi_match(Src, MRI, m_GFNeg(m_Reg(NegSrc)))) - return false; - - MatchInfo = [=, &MI](MachineIRBuilder &B) { - Observer.changingInstr(MI); - MI.getOperand(1).setReg(NegSrc); - Observer.changedInstr(MI); - }; - return true; -} - bool CombinerHelper::matchCombineTruncOfExt( MachineInstr &MI, std::pair &MatchInfo) { assert(MI.getOpcode() == TargetOpcode::G_TRUNC && "Expected a G_TRUNC"); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir @@ -27,7 +27,7 @@ ; CHECK-LABEL: name: test_combine_select_undef_res0_res1 ; CHECK: liveins: $x0, $x1 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) %0:_(s64) = COPY $x0 %1:_(s64) = COPY $x1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-select.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-select.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizercombiner-select.mir @@ -27,7 +27,7 @@ ; CHECK-LABEL: name: test_combine_select_undef_res0_res1 ; CHECK: liveins: $x0, $x1 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x1 ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) %0:_(s64) = COPY $x0 %1:_(s64) = COPY $x1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir @@ -46,11 +46,14 @@ bb.0: ; %load1 || %load2 == %load1 is fine here, because the loads are invariant. + ; TODO: Loads need to be CSE'd for this to work. ; CHECK-LABEL: name: invariant_loads ; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g + ; CHECK-NEXT: %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) ; CHECK-NEXT: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) - ; CHECK-NEXT: G_STORE %load2(s32), %ptr(p0) :: (store (s32) into @g) + ; CHECK-NEXT: %or:_(s32) = G_OR %load2, %load1 + ; CHECK-NEXT: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = G_GLOBAL_VALUE @g %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir @@ -63,7 +63,6 @@ ... -# FIXME: Probably should be able to replace this. --- name: mul_0_cant_replace tracksRegLiveness: true @@ -75,9 +74,8 @@ ; CHECK-LABEL: name: mul_0_cant_replace ; CHECK: liveins: $w0 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: %x:_(s32) = COPY $w0 ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0 - ; CHECK-NEXT: %op:gpr(s32) = G_MUL %x, %cst + ; CHECK-NEXT: %op:gpr(s32) = COPY %cst(s32) ; CHECK-NEXT: $w0 = COPY %op(s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 %x:_(s32) = COPY $w0 @@ -312,7 +310,9 @@ ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %zero:_(s8) = G_CONSTANT i8 0 ; CHECK-NEXT: %zext_zero:_(s64) = G_ZEXT %zero(s8) - ; CHECK-NEXT: $x0 = COPY %zext_zero(s64) + ; CHECK-NEXT: %c:_(s64) = G_CONSTANT i64 72340172838076673 + ; CHECK-NEXT: %mul:_(s64) = G_MUL %zext_zero, %c + ; CHECK-NEXT: $x0 = COPY %mul(s64) ; CHECK-NEXT: RET_ReallyLR implicit $x0 %zero:_(s8) = G_CONSTANT i8 0 %zext_zero:_(s64) = G_ZEXT %zero(s8)