diff --git a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp --- a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp +++ b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp @@ -323,17 +323,24 @@ unsigned PosOpc, unsigned NegOpc, MachineInstr &MI) { // Try below transformation. // - // MOVi32imm + ADDWrr ==> ADDWri + ADDWri - // MOVi64imm + ADDXrr ==> ADDXri + ADDXri + // ADDWrr X, MOVi32imm ==> ADDWri + ADDWri + // ADDXrr X, MOVi64imm ==> ADDXri + ADDXri // - // MOVi32imm + SUBWrr ==> SUBWri + SUBWri - // MOVi64imm + SUBXrr ==> SUBXri + SUBXri + // SUBWrr X, MOVi32imm ==> SUBWri + SUBWri + // SUBXrr X, MOVi64imm ==> SUBXri + SUBXri // // The mov pseudo instruction could be expanded to multiple mov instructions // later. Let's try to split the constant operand of mov instruction into two // legal add/sub immediates. It makes only two ADD/SUB instructions intead of // multiple `mov` + `and/sub` instructions. + // We can sometimes have ADDWrr WZR, MULi32imm that have not been constant + // folded. Make sure that we don't generate invalid instructions that use XZR + // in those cases. + if (MI.getOperand(1).getReg() == AArch64::XZR || + MI.getOperand(1).getReg() == AArch64::WZR) + return false; + return splitTwoPartImm( MI, [PosOpc, NegOpc](T Imm, unsigned RegSize, T &Imm0, @@ -365,6 +372,11 @@ OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI) { // Try the same transformation as ADDSUB but with additional requirement // that the condition code usages are only for Equal and Not Equal + + if (MI.getOperand(1).getReg() == AArch64::XZR || + MI.getOperand(1).getReg() == AArch64::WZR) + return false; + return splitTwoPartImm( MI, [PosOpcs, NegOpcs, &MI, &TRI = TRI, diff --git a/llvm/test/CodeGen/AArch64/addsub-24bit-imm.mir b/llvm/test/CodeGen/AArch64/addsub-24bit-imm.mir --- a/llvm/test/CodeGen/AArch64/addsub-24bit-imm.mir +++ b/llvm/test/CodeGen/AArch64/addsub-24bit-imm.mir @@ -10,7 +10,9 @@ bb.0.entry: liveins: $w0 ; CHECK-LABEL: name: addi - ; CHECK: [[COPY:%[0-9]+]]:gpr32common = COPY $w0 + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32common = COPY $w0 ; CHECK-NEXT: [[ADDWri:%[0-9]+]]:gpr32sp = ADDWri [[COPY]], 273, 12 ; CHECK-NEXT: [[ADDWri1:%[0-9]+]]:gpr32common = ADDWri [[ADDWri]], 3549, 0 ; CHECK-NEXT: [[UBFMWri:%[0-9]+]]:gpr32 = UBFMWri [[ADDWri1]], 28, 31 @@ -29,7 +31,9 @@ bb.0.entry: liveins: $x0 ; CHECK-LABEL: name: addl - ; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x0 + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY $x0 ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64sp = ADDXri [[COPY]], 273, 12 ; CHECK-NEXT: [[ADDXri1:%[0-9]+]]:gpr64common = ADDXri [[ADDXri]], 3549, 0 ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri [[ADDXri1]], 28, 31 @@ -49,7 +53,9 @@ bb.0.entry: liveins: $x0 ; CHECK-LABEL: name: addl_negate - ; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY $x0 + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY $x0 ; CHECK-NEXT: [[SUBXri:%[0-9]+]]:gpr64sp = SUBXri [[COPY]], 273, 12 ; CHECK-NEXT: [[SUBXri1:%[0-9]+]]:gpr64common = SUBXri [[SUBXri]], 3549, 0 ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri [[SUBXri1]], 28, 31 @@ -61,3 +67,87 @@ %3:gpr64 = UBFMXri %2, 28, 31 $x0 = COPY %3 RET_ReallyLR implicit $x0 +... +--- +name: add_xzr +body: | + bb.0.entry: + liveins: $x0 + ; CHECK-LABEL: name: add_xzr + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr $xzr, [[MOVi64imm]] + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[ADDXrr]] + ; CHECK-NEXT: $x0 = COPY [[MADDXrrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %0:gpr64 = COPY $x0 + %2:gpr64 = MOVi64imm -2105098 + %4:gpr64common = ADDXrr $xzr, %2 + %3:gpr64 = MADDXrrr %0, %0, %4 + $x0 = COPY %3 + RET_ReallyLR implicit $x0 +... +--- +name: sub_xzr +body: | + bb.0.entry: + liveins: $x0 + ; CHECK-LABEL: name: sub_xzr + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098 + ; CHECK-NEXT: [[SUBXrr:%[0-9]+]]:gpr64common = SUBXrr $xzr, [[MOVi64imm]] + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[SUBXrr]] + ; CHECK-NEXT: $x0 = COPY [[MADDXrrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %0:gpr64 = COPY $x0 + %2:gpr64 = MOVi64imm -2105098 + %4:gpr64common = SUBXrr $xzr, %2 + %3:gpr64 = MADDXrrr %0, %0, %4 + $x0 = COPY %3 + RET_ReallyLR implicit $x0 +... +--- +name: adds_xzr +body: | + bb.0.entry: + liveins: $x0 + ; CHECK-LABEL: name: adds_xzr + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098 + ; CHECK-NEXT: [[ADDSXrr:%[0-9]+]]:gpr64common = ADDSXrr $xzr, [[MOVi64imm]], implicit-def $nzcv + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[ADDSXrr]] + ; CHECK-NEXT: $x0 = COPY [[MADDXrrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %0:gpr64 = COPY $x0 + %2:gpr64 = MOVi64imm -2105098 + %4:gpr64common = ADDSXrr $xzr, %2, implicit-def $nzcv + %3:gpr64 = MADDXrrr %0, %0, %4 + $x0 = COPY %3 + RET_ReallyLR implicit $x0 +... +--- +name: subs_xzr +body: | + bb.0.entry: + liveins: $x0 + ; CHECK-LABEL: name: subs_xzr + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm -2105098 + ; CHECK-NEXT: [[SUBSXrr:%[0-9]+]]:gpr64common = SUBSXrr $xzr, [[MOVi64imm]], implicit-def $nzcv + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY]], [[SUBSXrr]] + ; CHECK-NEXT: $x0 = COPY [[MADDXrrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %0:gpr64 = COPY $x0 + %2:gpr64 = MOVi64imm -2105098 + %4:gpr64common = SUBSXrr $xzr, %2, implicit-def $nzcv + %3:gpr64 = MADDXrrr %0, %0, %4 + $x0 = COPY %3 + RET_ReallyLR implicit $x0