diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 05d7e882f5135..c76a54ed26ed5 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -892,6 +892,16 @@ class CombinerHelper { bool matchCastOfSelect(const MachineInstr &Cast, const MachineInstr &SelectMI, BuildFnTy &MatchInfo); + bool matchFoldAPlusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo); + + bool matchFoldC2MinusAPlusC1(const MachineInstr &MI, BuildFnTy &MatchInfo); + + bool matchFoldAMinusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo); + + bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo); + + // fold ((A-C1)+C2) -> (A+(C2-C1)) + bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo); private: /// Checks for legality of an indexed variant of \p LdSt. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h index 08736acebca8a..cf5fd6d6f288b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -22,6 +22,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/Casting.h" + #include namespace llvm { @@ -178,6 +179,9 @@ std::optional getIConstantVRegVal(Register VReg, std::optional getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI); +/// \p VReg is defined by a G_CONSTANT, return the corresponding value. +APInt getIConstantFromReg(Register VReg, const MachineRegisterInfo &MRI); + /// Simple struct used to hold a constant integer value and a virtual /// register. struct ValueAndVReg { diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 1f26132561cca..54fb14d24b48e 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -1747,6 +1747,56 @@ def APlusBMinusCPlusA : GICombineRule< (G_ADD $root, $A, $sub1)), (apply (G_SUB $root, $B, $C))>; +// fold (A+C1)-C2 -> A+(C1-C2) +def APlusC1MinusC2: GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_CONSTANT $c2, $imm2), + (G_CONSTANT $c1, $imm1), + (G_ADD $add, $A, $c1), + (G_SUB $root, $add, $c2):$root, + [{ return Helper.matchFoldAPlusC1MinusC2(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +// fold C2-(A+C1) -> (C2-C1)-A +def C2MinusAPlusC1: GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_CONSTANT $c2, $imm2), + (G_CONSTANT $c1, $imm1), + (G_ADD $add, $A, $c1), + (G_SUB $root, $c2, $add):$root, + [{ return Helper.matchFoldC2MinusAPlusC1(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +// fold (A-C1)-C2 -> A-(C1+C2) +def AMinusC1MinusC2: GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_CONSTANT $c2, $imm2), + (G_CONSTANT $c1, $imm1), + (G_SUB $sub1, $A, $c1), + (G_SUB $root, $sub1, $c2):$root, + [{ return Helper.matchFoldAMinusC1MinusC2(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +// fold (C1-A)-C2 -> (C1-C2)-A +def C1Minus2MinusC2: GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_CONSTANT $c2, $imm2), + (G_CONSTANT $c1, $imm1), + (G_SUB $sub1, $c1, $A), + (G_SUB $root, $sub1, $c2):$root, + [{ return Helper.matchFoldC1Minus2MinusC2(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +// fold ((A-C1)+C2) -> (A+(C2-C1)) +def AMinusC1PlusC2: GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_CONSTANT $c2, $imm2), + (G_CONSTANT $c1, $imm1), + (G_SUB $sub, $A, $c1), + (G_ADD $root, $sub, $c2):$root, + [{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + def integer_reassoc_combines: GICombineGroup<[ ZeroMinusAPlusB, APlusZeroMinusB, @@ -1755,7 +1805,12 @@ def integer_reassoc_combines: GICombineGroup<[ AMinusBPlusCMinusA, AMinusBPlusBMinusC, APlusBMinusAplusC, - APlusBMinusCPlusA + APlusBMinusCPlusA, + APlusC1MinusC2, + C2MinusAPlusC1, + AMinusC1MinusC2, + C1Minus2MinusC2, + AMinusC1PlusC2 ]>; def freeze_of_non_undef_non_poison : GICombineRule< diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index d930ab2984629..d363e6794cb01 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -7433,3 +7433,118 @@ void CombinerHelper::applyExpandFPowI(MachineInstr &MI, int64_t Exponent) { Builder.buildCopy(Dst, *Res); MI.eraseFromParent(); } + +bool CombinerHelper::matchFoldAPlusC1MinusC2(const MachineInstr &MI, + BuildFnTy &MatchInfo) { + // fold (A+C1)-C2 -> A+(C1-C2) + const GSub *Sub = cast(&MI); + GAdd *Add = cast(MRI.getVRegDef(Sub->getLHSReg())); + + if (!MRI.hasOneNonDBGUse(Add->getReg(0))) + return false; + + APInt C2 = getIConstantFromReg(Sub->getRHSReg(), MRI); + APInt C1 = getIConstantFromReg(Add->getRHSReg(), MRI); + + Register Dst = Sub->getReg(0); + LLT DstTy = MRI.getType(Dst); + + MatchInfo = [=](MachineIRBuilder &B) { + auto Const = B.buildConstant(DstTy, C1 - C2); + B.buildAdd(Dst, Add->getLHSReg(), Const); + }; + + return true; +} + +bool CombinerHelper::matchFoldC2MinusAPlusC1(const MachineInstr &MI, + BuildFnTy &MatchInfo) { + // fold C2-(A+C1) -> (C2-C1)-A + const GSub *Sub = cast(&MI); + GAdd *Add = cast(MRI.getVRegDef(Sub->getRHSReg())); + + if (!MRI.hasOneNonDBGUse(Add->getReg(0))) + return false; + + APInt C2 = getIConstantFromReg(Sub->getLHSReg(), MRI); + APInt C1 = getIConstantFromReg(Add->getRHSReg(), MRI); + + Register Dst = Sub->getReg(0); + LLT DstTy = MRI.getType(Dst); + + MatchInfo = [=](MachineIRBuilder &B) { + auto Const = B.buildConstant(DstTy, C2 - C1); + B.buildSub(Dst, Const, Add->getLHSReg()); + }; + + return true; +} + +bool CombinerHelper::matchFoldAMinusC1MinusC2(const MachineInstr &MI, + BuildFnTy &MatchInfo) { + // fold (A-C1)-C2 -> A-(C1+C2) + const GSub *Sub1 = cast(&MI); + GSub *Sub2 = cast(MRI.getVRegDef(Sub1->getLHSReg())); + + if (!MRI.hasOneNonDBGUse(Sub2->getReg(0))) + return false; + + APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI); + APInt C1 = getIConstantFromReg(Sub2->getRHSReg(), MRI); + + Register Dst = Sub1->getReg(0); + LLT DstTy = MRI.getType(Dst); + + MatchInfo = [=](MachineIRBuilder &B) { + auto Const = B.buildConstant(DstTy, C1 + C2); + B.buildSub(Dst, Sub2->getLHSReg(), Const); + }; + + return true; +} + +bool CombinerHelper::matchFoldC1Minus2MinusC2(const MachineInstr &MI, + BuildFnTy &MatchInfo) { + // fold (C1-A)-C2 -> (C1-C2)-A + const GSub *Sub1 = cast(&MI); + GSub *Sub2 = cast(MRI.getVRegDef(Sub1->getLHSReg())); + + if (!MRI.hasOneNonDBGUse(Sub2->getReg(0))) + return false; + + APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI); + APInt C1 = getIConstantFromReg(Sub2->getLHSReg(), MRI); + + Register Dst = Sub1->getReg(0); + LLT DstTy = MRI.getType(Dst); + + MatchInfo = [=](MachineIRBuilder &B) { + auto Const = B.buildConstant(DstTy, C1 - C2); + B.buildSub(Dst, Const, Sub2->getRHSReg()); + }; + + return true; +} + +bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI, + BuildFnTy &MatchInfo) { + // fold ((A-C1)+C2) -> (A+(C2-C1)) + const GAdd *Add = cast(&MI); + GSub *Sub = cast(MRI.getVRegDef(Add->getLHSReg())); + + if (!MRI.hasOneNonDBGUse(Sub->getReg(0))) + return false; + + APInt C2 = getIConstantFromReg(Add->getRHSReg(), MRI); + APInt C1 = getIConstantFromReg(Sub->getRHSReg(), MRI); + + Register Dst = Add->getReg(0); + LLT DstTy = MRI.getType(Dst); + + MatchInfo = [=](MachineIRBuilder &B) { + auto Const = B.buildConstant(DstTy, C2 - C1); + B.buildAdd(Dst, Sub->getLHSReg(), Const); + }; + + return true; +} diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index 080664843aaeb..cfdd9905c16fa 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -303,6 +303,13 @@ std::optional llvm::getIConstantVRegVal(Register VReg, return ValAndVReg->Value; } +APInt llvm::getIConstantFromReg(Register Reg, const MachineRegisterInfo &MRI) { + MachineInstr *Const = MRI.getVRegDef(Reg); + assert((Const && Const->getOpcode() == TargetOpcode::G_CONSTANT) && + "expected a G_CONSTANT on Reg"); + return Const->getOperand(1).getCImm()->getValue(); +} + std::optional llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) { std::optional Val = getIConstantVRegVal(VReg, MRI); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir index ac42d2da16d56..6bd1d996da85f 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir @@ -3,12 +3,12 @@ ... --- +# (x + y) - y -> x name: simplify_to_x tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; (x + y) - y -> x ; CHECK-LABEL: name: simplify_to_x ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -23,12 +23,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# (x + y) - x -> y name: simplify_to_y tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; (x + y) - x -> y ; CHECK-LABEL: name: simplify_to_y ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -43,12 +43,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# (x + 1) - 1 -> x name: simplify_to_constant_x tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; (x + 1) - 1 -> x ; CHECK-LABEL: name: simplify_to_constant_x ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -64,12 +64,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# (x + y) - x -> y name: simplify_to_constant_y tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; (x + y) - x -> y ; CHECK-LABEL: name: simplify_to_constant_y ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -85,12 +85,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# (x + y) - y -> x name: vector_simplify_to_x tracksRegLiveness: true body: | bb.0: liveins: $d0, $d1 - ; (x + y) - y -> x ; CHECK-LABEL: name: vector_simplify_to_x ; CHECK: liveins: $d0, $d1 ; CHECK-NEXT: {{ $}} @@ -105,12 +105,12 @@ body: | RET_ReallyLR implicit $d0 ... --- +# (x + 1) - 1 -> x name: splat_simplify_to_x tracksRegLiveness: true body: | bb.0: liveins: $d0, $d1 - ; (x + 1) - 1 -> x ; CHECK-LABEL: name: splat_simplify_to_x ; CHECK: liveins: $d0, $d1 ; CHECK-NEXT: {{ $}} @@ -127,6 +127,7 @@ body: | RET_ReallyLR implicit $d0 ... --- +# (x + y) - x -> y name: unique_registers_no_fold tracksRegLiveness: true body: | @@ -151,20 +152,18 @@ body: | RET_ReallyLR implicit $w0 ... --- +# (x + y) - x -> y name: unique_constants_no_fold tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; (x + y) - x -> y ; CHECK-LABEL: name: unique_constants_no_fold ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: %x1:_(s32) = G_CONSTANT i32 1 - ; CHECK-NEXT: %x2:_(s32) = G_CONSTANT i32 2 ; CHECK-NEXT: %y:_(s32) = COPY $w1 - ; CHECK-NEXT: %add:_(s32) = G_ADD %y, %x1 - ; CHECK-NEXT: %sub:_(s32) = G_SUB %add, %x2 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: %sub:_(s32) = G_ADD %y, [[C]] ; CHECK-NEXT: $w0 = COPY %sub(s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 %x1:_(s32) = G_CONSTANT i32 1 @@ -176,12 +175,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# x - (y + x) -> 0 - y name: simplify_to_neg_y tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; x - (y + x) -> 0 - y ; CHECK-LABEL: name: simplify_to_neg_y ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -198,12 +197,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# y - (y + x) -> 0 - x name: simplify_to_neg_x tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; y - (y + x) -> 0 - x ; CHECK-LABEL: name: simplify_to_neg_x ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -220,12 +219,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# x - (y + x) -> 0 - y name: simplify_to_neg_y_constant tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; x - (y + x) -> 0 - y ; CHECK-LABEL: name: simplify_to_neg_y_constant ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -243,12 +242,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# y - (y + x) -> 0 - x name: simplify_to_neg_x_constant tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; y - (y + x) -> 0 - x ; CHECK-LABEL: name: simplify_to_neg_x_constant ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} @@ -266,12 +265,12 @@ body: | RET_ReallyLR implicit $w0 ... --- +# y - (y + x) -> 0 - x name: vector_simplify_to_neg_x tracksRegLiveness: true body: | bb.0: liveins: $d0, $d1 - ; y - (y + x) -> 0 - x ; CHECK-LABEL: name: vector_simplify_to_neg_x ; CHECK: liveins: $d0, $d1 ; CHECK-NEXT: {{ $}} @@ -289,12 +288,12 @@ body: | RET_ReallyLR implicit $d0 ... --- +# x - (y + x) -> 0 - y name: vector_simplify_to_neg_y_constant tracksRegLiveness: true body: | bb.0: liveins: $d0, $d1 - ; x - (y + x) -> 0 - y ; CHECK-LABEL: name: vector_simplify_to_neg_y_constant ; CHECK: liveins: $d0, $d1 ; CHECK-NEXT: {{ $}} @@ -314,12 +313,12 @@ body: | RET_ReallyLR implicit $d0 ... --- +# y - (y + x) -> 0 - x name: unique_registers_neg_no_fold tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1, $w2 - ; y - (y + x) -> 0 - x ; CHECK-LABEL: name: unique_registers_neg_no_fold ; CHECK: liveins: $w0, $w1, $w2 ; CHECK-NEXT: {{ $}} @@ -339,20 +338,18 @@ body: | RET_ReallyLR implicit $w0 ... --- +# x - (y + x) -> 0 - y name: wrong_constant_neg_no_fold tracksRegLiveness: true body: | bb.0: liveins: $w0, $w1 - ; x - (y + x) -> 0 - y ; CHECK-LABEL: name: wrong_constant_neg_no_fold ; CHECK: liveins: $w0, $w1 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %x1:_(s32) = G_CONSTANT i32 1 - ; CHECK-NEXT: %x2:_(s32) = G_CONSTANT i32 2 ; CHECK-NEXT: %y:_(s32) = COPY $w1 - ; CHECK-NEXT: %add:_(s32) = G_ADD %y, %x1 - ; CHECK-NEXT: %sub:_(s32) = G_SUB %x2, %add + ; CHECK-NEXT: %sub:_(s32) = G_SUB %x1, %y ; CHECK-NEXT: $w0 = COPY %sub(s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 %x1:_(s32) = G_CONSTANT i32 1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll new file mode 100644 index 0000000000000..03dcbafd73e87 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll @@ -0,0 +1,71 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI + + + +define i64 @APlusC1MinusC2(i64 %a) { +; CHECK-LABEL: APlusC1MinusC2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub x0, x0, #1 +; CHECK-NEXT: ret +entry: +; fold (A+C1)-C2 -> A+(C1-C2) + %add1 = add i64 %a, 5 + %sub1 = sub i64 %add1, 6 + ret i64 %sub1 +} + +define i64 @C2MinusAPlusC1(i64 %a) { +; CHECK-LABEL: C2MinusAPlusC1: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w8, #3 // =0x3 +; CHECK-NEXT: sub x0, x8, x0 +; CHECK-NEXT: ret +entry: +; fold C2-(A+C1) -> (C2-C1)-A + %add1 = add i64 %a, 6 + %sub1 = sub i64 9, %add1 + ret i64 %sub1 +} + +define i64 @AMinusC1MinusC2(i64 %a) { +; CHECK-LABEL: AMinusC1MinusC2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub x0, x0, #15 +; CHECK-NEXT: ret +entry: +; fold (A-C1)-C2 -> A-(C1+C2) + %sub2 = sub i64 %a, 6 + %sub1 = sub i64 %sub2, 9 + ret i64 %sub1 +} + +define i64 @C1Minus2MinusC2(i64 %a) { +; CHECK-LABEL: C1Minus2MinusC2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w8, #3 // =0x3 +; CHECK-NEXT: sub x0, x8, x0 +; CHECK-NEXT: ret +entry: +; fold (C1-A)-C2 -> (C1-C2)-A + %sub2 = sub i64 14, %a + %sub1 = sub i64 %sub2, 11 + ret i64 %sub1 +} + +define i64 @AMinusC2PlusC2(i64 %a) { +; CHECK-LABEL: AMinusC2PlusC2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub x0, x0, #4 +; CHECK-NEXT: ret +entry: +; fold ((A-C1)+C2) -> (A+(C2-C1)) + %sub1 = sub i64 %a, 21 + %add1 = add i64 %sub1, 17 + ret i64 %add1 +} + +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK-GI: {{.*}} +; CHECK-SD: {{.*}} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir index be33f9f7b284b..2f10a497fa74c 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir @@ -250,3 +250,120 @@ body: | %add:_(<2 x s64>) = G_ADD %a, %sub1 $q0 = COPY %add RET_ReallyLR implicit $x0 + +... +--- +name: APlusC1MinusC2 +body: | + bb.0: + liveins: $w0, $w1 + + ; CHECK-LABEL: name: APlusC1MinusC2 + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %a:_(s64) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -2 + ; CHECK-NEXT: %sub:_(s64) = G_ADD %a, [[C]] + ; CHECK-NEXT: $x0 = COPY %sub(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %a:_(s64) = COPY $x0 + %c1:_(s64) = G_CONSTANT i64 5 + %c2:_(s64) = G_CONSTANT i64 7 + %add:_(s64) = G_ADD %a, %c1 + %sub:_(s64) = G_SUB %add, %c2 + $x0 = COPY %sub + RET_ReallyLR implicit $x0 + +... +--- +name: C2MinusAPlusC1 +body: | + bb.0: + liveins: $w0, $w1 + + ; CHECK-LABEL: name: C2MinusAPlusC1 + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %a:_(s64) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; CHECK-NEXT: %sub:_(s64) = G_SUB [[C]], %a + ; CHECK-NEXT: $x0 = COPY %sub(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %a:_(s64) = COPY $x0 + %c1:_(s64) = G_CONSTANT i64 4 + %c2:_(s64) = G_CONSTANT i64 9 + %add:_(s64) = G_ADD %a, %c1 + %sub:_(s64) = G_SUB %c2, %add + $x0 = COPY %sub + RET_ReallyLR implicit $x0 + +... +--- +name: AMinusC1MinusC2 +body: | + bb.0: + liveins: $w0, $w1 + + ; CHECK-LABEL: name: AMinusC1MinusC2 + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %a:_(s64) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 71 + ; CHECK-NEXT: %sub:_(s64) = G_SUB %a, [[C]] + ; CHECK-NEXT: $x0 = COPY %sub(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %a:_(s64) = COPY $x0 + %c1:_(s64) = G_CONSTANT i64 11 + %c2:_(s64) = G_CONSTANT i64 60 + %sub1:_(s64) = G_SUB %a, %c1 + %sub:_(s64) = G_SUB %sub1, %c2 + $x0 = COPY %sub + RET_ReallyLR implicit $x0 + +... +--- +name: C1Minus2MinusC2 +body: | + bb.0: + liveins: $w0, $w1 + + ; CHECK-LABEL: name: C1Minus2MinusC2 + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %a:_(s64) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -49 + ; CHECK-NEXT: %sub:_(s64) = G_SUB [[C]], %a + ; CHECK-NEXT: $x0 = COPY %sub(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %a:_(s64) = COPY $x0 + %c1:_(s64) = G_CONSTANT i64 11 + %c2:_(s64) = G_CONSTANT i64 60 + %sub1:_(s64) = G_SUB %c1, %a + %sub:_(s64) = G_SUB %sub1, %c2 + $x0 = COPY %sub + RET_ReallyLR implicit $x0 + + +... +--- +name: AMinusC2PlusC2 +body: | + bb.0: + liveins: $w0, $w1 + + ; CHECK-LABEL: name: AMinusC2PlusC2 + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %a:_(s64) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 43 + ; CHECK-NEXT: %add:_(s64) = G_ADD %a, [[C]] + ; CHECK-NEXT: $x0 = COPY %add(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %a:_(s64) = COPY $x0 + %c1:_(s64) = G_CONSTANT i64 13 + %c2:_(s64) = G_CONSTANT i64 56 + %sub:_(s64) = G_SUB %a, %c1 + %add:_(s64) = G_ADD %sub, %c2 + $x0 = COPY %add + RET_ReallyLR implicit $x0 +