diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index c3b494e94ff1dc..a2c0899fd18bde 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -170,8 +170,8 @@ class LegalizerHelper { widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); LegalizeResult widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); - LegalizeResult widenScalarAddoSubo(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); + LegalizeResult widenScalarAddSubOverflow(MachineInstr &MI, unsigned TypeIdx, + LLT WideTy); LegalizeResult widenScalarAddSubShlSat(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index e7f40523efafd3..9fbbdd1ccdf5da 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1758,22 +1758,68 @@ LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, } LegalizerHelper::LegalizeResult -LegalizerHelper::widenScalarAddoSubo(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy) { +LegalizerHelper::widenScalarAddSubOverflow(MachineInstr &MI, unsigned TypeIdx, + LLT WideTy) { if (TypeIdx == 1) return UnableToLegalize; // TODO - unsigned Op = MI.getOpcode(); - unsigned Opcode = Op == TargetOpcode::G_UADDO || Op == TargetOpcode::G_SADDO - ? TargetOpcode::G_ADD - : TargetOpcode::G_SUB; - unsigned ExtOpcode = - Op == TargetOpcode::G_UADDO || Op == TargetOpcode::G_USUBO - ? TargetOpcode::G_ZEXT - : TargetOpcode::G_SEXT; + + unsigned Opcode; + unsigned ExtOpcode; + Optional CarryIn = None; + switch (MI.getOpcode()) { + default: + llvm_unreachable("Unexpected opcode!"); + case TargetOpcode::G_SADDO: + Opcode = TargetOpcode::G_ADD; + ExtOpcode = TargetOpcode::G_SEXT; + break; + case TargetOpcode::G_SSUBO: + Opcode = TargetOpcode::G_SUB; + ExtOpcode = TargetOpcode::G_SEXT; + break; + case TargetOpcode::G_UADDO: + Opcode = TargetOpcode::G_ADD; + ExtOpcode = TargetOpcode::G_ZEXT; + break; + case TargetOpcode::G_USUBO: + Opcode = TargetOpcode::G_SUB; + ExtOpcode = TargetOpcode::G_ZEXT; + break; + case TargetOpcode::G_SADDE: + Opcode = TargetOpcode::G_UADDE; + ExtOpcode = TargetOpcode::G_SEXT; + CarryIn = MI.getOperand(4).getReg(); + break; + case TargetOpcode::G_SSUBE: + Opcode = TargetOpcode::G_USUBE; + ExtOpcode = TargetOpcode::G_SEXT; + CarryIn = MI.getOperand(4).getReg(); + break; + case TargetOpcode::G_UADDE: + Opcode = TargetOpcode::G_UADDE; + ExtOpcode = TargetOpcode::G_ZEXT; + CarryIn = MI.getOperand(4).getReg(); + break; + case TargetOpcode::G_USUBE: + Opcode = TargetOpcode::G_USUBE; + ExtOpcode = TargetOpcode::G_ZEXT; + CarryIn = MI.getOperand(4).getReg(); + break; + } + auto LHSExt = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MI.getOperand(2)}); auto RHSExt = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MI.getOperand(3)}); // Do the arithmetic in the larger type. - auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}); + Register NewOp; + if (CarryIn) { + LLT CarryOutTy = MRI.getType(MI.getOperand(1).getReg()); + NewOp = MIRBuilder + .buildInstr(Opcode, {WideTy, CarryOutTy}, + {LHSExt, RHSExt, *CarryIn}) + .getReg(0); + } else { + NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).getReg(0); + } LLT OrigTy = MRI.getType(MI.getOperand(0).getReg()); auto TruncOp = MIRBuilder.buildTrunc(OrigTy, NewOp); auto ExtOp = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp}); @@ -1846,7 +1892,11 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { case TargetOpcode::G_SSUBO: case TargetOpcode::G_UADDO: case TargetOpcode::G_USUBO: - return widenScalarAddoSubo(MI, TypeIdx, WideTy); + case TargetOpcode::G_SADDE: + case TargetOpcode::G_SSUBE: + case TargetOpcode::G_UADDE: + case TargetOpcode::G_USUBE: + return widenScalarAddSubOverflow(MI, TypeIdx, WideTy); case TargetOpcode::G_SADDSAT: case TargetOpcode::G_SSUBSAT: case TargetOpcode::G_SSHLSAT: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sadde.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sadde.mir index 2540aaa35fcef8..367f0ee5988719 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sadde.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-sadde.mir @@ -1,6 +1,42 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple aarch64 -verify-machineinstrs -run-pass=legalizer -debugify-and-strip-all-safe %s -o - | FileCheck %s +--- +name: widen_scalar_sadde_s8 +body: | + bb.0.entry: + ; CHECK-LABEL: name: widen_scalar_sadde_s8 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x2 + ; CHECK: %carry_in:_(s1) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC]], 8 + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[SEXT_INREG]], [[SEXT_INREG1]], %carry_in + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[UADDE]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[UADDE]](s32) + ; CHECK: [[SEXT_INREG2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY3]], 8 + ; CHECK: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[UADDE]](s32), [[SEXT_INREG2]] + ; CHECK: %add:_(s8) = COPY [[TRUNC2]](s8) + ; CHECK: %add_ext:_(s64) = G_ANYEXT [[UADDE]](s32) + ; CHECK: %carry_out_ext:_(s64) = G_ANYEXT [[ICMP]](s32) + ; CHECK: $x0 = COPY %add_ext(s64) + ; CHECK: $x1 = COPY %carry_out_ext(s64) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY $x1 + %2:_(s64) = COPY $x2 + %lhs:_(s8) = G_TRUNC %0 + %rhs:_(s8) = G_TRUNC %1 + %carry_in:_(s1) = G_TRUNC %2 + %add:_(s8), %carry_out:_(s1) = G_SADDE %lhs, %rhs, %carry_in + %add_ext:_(s64) = G_ANYEXT %add + %carry_out_ext:_(s64) = G_ANYEXT %carry_out + $x0 = COPY %add_ext + $x1 = COPY %carry_out_ext + +... --- name: test_scalar_sadde_32 body: | diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ssube.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ssube.mir index 1c667499eb32e2..7e23740e3a4c24 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ssube.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ssube.mir @@ -1,6 +1,42 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple aarch64 -verify-machineinstrs -run-pass=legalizer -debugify-and-strip-all-safe %s -o - | FileCheck %s +--- +name: widen_scalar_ssube_s8 +body: | + bb.0.entry: + ; CHECK-LABEL: name: widen_scalar_ssube_s8 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x2 + ; CHECK: %carry_in:_(s1) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC]], 8 + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[TRUNC1]], 8 + ; CHECK: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[SEXT_INREG]], [[SEXT_INREG1]], %carry_in + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[USUBE]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[USUBE]](s32) + ; CHECK: [[SEXT_INREG2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY3]], 8 + ; CHECK: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[USUBE]](s32), [[SEXT_INREG2]] + ; CHECK: %sub:_(s8) = COPY [[TRUNC2]](s8) + ; CHECK: %sub_ext:_(s64) = G_ANYEXT [[USUBE]](s32) + ; CHECK: %carry_out_ext:_(s64) = G_ANYEXT [[ICMP]](s32) + ; CHECK: $x0 = COPY %sub_ext(s64) + ; CHECK: $x1 = COPY %carry_out_ext(s64) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY $x1 + %2:_(s64) = COPY $x2 + %lhs:_(s8) = G_TRUNC %0 + %rhs:_(s8) = G_TRUNC %1 + %carry_in:_(s1) = G_TRUNC %2 + %sub:_(s8), %carry_out:_(s1) = G_SSUBE %lhs, %rhs, %carry_in + %sub_ext:_(s64) = G_ANYEXT %sub + %carry_out_ext:_(s64) = G_ANYEXT %carry_out + $x0 = COPY %sub_ext + $x1 = COPY %carry_out_ext + +... --- name: test_scalar_ssube_32 body: | diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-uadde.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-uadde.mir index 3b73ddf67f5ae4..236f42a2269dad 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-uadde.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-uadde.mir @@ -1,6 +1,43 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple aarch64 -verify-machineinstrs -run-pass=legalizer -debugify-and-strip-all-safe %s -o - | FileCheck %s +--- +name: widen_scalar_uadde_s8 +body: | + bb.0.entry: + ; CHECK-LABEL: name: widen_scalar_uadde_s8 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x2 + ; CHECK: %carry_in:_(s1) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC]], [[C]] + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC1]], [[C]] + ; CHECK: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[AND]], [[AND1]], %carry_in + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[UADDE]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[UADDE]](s32) + ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; CHECK: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[UADDE]](s32), [[AND2]] + ; CHECK: %add:_(s8) = COPY [[TRUNC2]](s8) + ; CHECK: %add_ext:_(s64) = G_ANYEXT [[UADDE]](s32) + ; CHECK: %carry_out_ext:_(s64) = G_ANYEXT [[ICMP]](s32) + ; CHECK: $x0 = COPY %add_ext(s64) + ; CHECK: $x1 = COPY %carry_out_ext(s64) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY $x1 + %2:_(s64) = COPY $x2 + %lhs:_(s8) = G_TRUNC %0 + %rhs:_(s8) = G_TRUNC %1 + %carry_in:_(s1) = G_TRUNC %2 + %add:_(s8), %carry_out:_(s1) = G_UADDE %lhs, %rhs, %carry_in + %add_ext:_(s64) = G_ANYEXT %add + %carry_out_ext:_(s64) = G_ANYEXT %carry_out + $x0 = COPY %add_ext + $x1 = COPY %carry_out_ext + +... --- name: test_scalar_uadde_32 body: | diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-usube.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-usube.mir index e0ba478b4516c7..f72a6885652f6c 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-usube.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-usube.mir @@ -1,6 +1,43 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple aarch64 -verify-machineinstrs -run-pass=legalizer -debugify-and-strip-all-safe %s -o - | FileCheck %s +--- +name: widen_scalar_usube_s8 +body: | + bb.0.entry: + ; CHECK-LABEL: name: widen_scalar_usube_s8 + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 + ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x2 + ; CHECK: %carry_in:_(s1) = G_TRUNC [[COPY2]](s64) + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC]], [[C]] + ; CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[TRUNC1]], [[C]] + ; CHECK: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[AND]], [[AND1]], %carry_in + ; CHECK: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[USUBE]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[USUBE]](s32) + ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; CHECK: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ne), [[USUBE]](s32), [[AND2]] + ; CHECK: %sub:_(s8) = COPY [[TRUNC2]](s8) + ; CHECK: %sub_ext:_(s64) = G_ANYEXT [[USUBE]](s32) + ; CHECK: %carry_out_ext:_(s64) = G_ANYEXT [[ICMP]](s32) + ; CHECK: $x0 = COPY %sub_ext(s64) + ; CHECK: $x1 = COPY %carry_out_ext(s64) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY $x1 + %2:_(s64) = COPY $x2 + %lhs:_(s8) = G_TRUNC %0 + %rhs:_(s8) = G_TRUNC %1 + %carry_in:_(s1) = G_TRUNC %2 + %sub:_(s8), %carry_out:_(s1) = G_USUBE %lhs, %rhs, %carry_in + %sub_ext:_(s64) = G_ANYEXT %sub + %carry_out_ext:_(s64) = G_ANYEXT %carry_out + $x0 = COPY %sub_ext + $x1 = COPY %carry_out_ext + +... --- name: test_scalar_usube_32 body: | diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sadde.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sadde.mir index 6f7c008068023a..01d616d57d1fca 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sadde.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sadde.mir @@ -69,12 +69,17 @@ body: | ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]] - ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[SADDE:%[0-9]+]]:_(s16), [[SADDE1:%[0-9]+]]:_(s1) = G_SADDE [[TRUNC1]], [[SADDE]], [[ICMP]] - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDE]](s16) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[SADDE1]](s1) - ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY3]], 16 + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY %13(s32) + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY4]], 16 + ; CHECK: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[SEXT_INREG]], [[SEXT_INREG1]], [[ICMP]] + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[UADDE]](s32) + ; CHECK: [[SEXT_INREG2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY5]], 16 + ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[UADDE]](s32), [[SEXT_INREG2]] + ; CHECK: [[COPY6:%[0-9]+]]:_(s32) = COPY [[UADDE]](s32) + ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP1]](s1) + ; CHECK: $vgpr0 = COPY [[COPY6]](s32) ; CHECK: $vgpr1 = COPY [[ZEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssube.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssube.mir index f666c09c0c089a..d1f8a530c49fe3 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssube.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssube.mir @@ -68,12 +68,17 @@ body: | ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]] - ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[SSUBE:%[0-9]+]]:_(s16), [[SSUBE1:%[0-9]+]]:_(s1) = G_SSUBE [[TRUNC1]], [[SSUBE]], [[ICMP]] - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBE]](s16) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[SSUBE1]](s1) - ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY3]], 16 + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY %13(s32) + ; CHECK: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY4]], 16 + ; CHECK: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[SEXT_INREG]], [[SEXT_INREG1]], [[ICMP]] + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[USUBE]](s32) + ; CHECK: [[SEXT_INREG2:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY5]], 16 + ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[USUBE]](s32), [[SEXT_INREG2]] + ; CHECK: [[COPY6:%[0-9]+]]:_(s32) = COPY [[USUBE]](s32) + ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP1]](s1) + ; CHECK: $vgpr0 = COPY [[COPY6]](s32) ; CHECK: $vgpr1 = COPY [[ZEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uadde.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uadde.mir index 0fb3361657c5dd..343c700498419f 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uadde.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uadde.mir @@ -88,12 +88,18 @@ body: | ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]] - ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[UADDE:%[0-9]+]]:_(s16), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[TRUNC1]], [[UADDE]], [[ICMP]] - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDE]](s16) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDE1]](s1) - ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY %13(s32) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C1]] + ; CHECK: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[AND]], [[AND1]], [[ICMP]] + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[UADDE]](s32) + ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY5]], [[C1]] + ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[UADDE]](s32), [[AND2]] + ; CHECK: [[COPY6:%[0-9]+]]:_(s32) = COPY [[UADDE]](s32) + ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP1]](s1) + ; CHECK: $vgpr0 = COPY [[COPY6]](s32) ; CHECK: $vgpr1 = COPY [[ZEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usube.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usube.mir index 9733f973028a58..8f8128827d734c 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usube.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usube.mir @@ -99,12 +99,18 @@ body: | ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[COPY2]](s32), [[C]] - ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[USUBE:%[0-9]+]]:_(s16), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[TRUNC1]], [[USUBE]], [[ICMP]] - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBE]](s16) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[USUBE1]](s1) - ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) + ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; CHECK: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C1]] + ; CHECK: [[COPY4:%[0-9]+]]:_(s32) = COPY %13(s32) + ; CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C1]] + ; CHECK: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[AND]], [[AND1]], [[ICMP]] + ; CHECK: [[COPY5:%[0-9]+]]:_(s32) = COPY [[USUBE]](s32) + ; CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY5]], [[C1]] + ; CHECK: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(ne), [[USUBE]](s32), [[AND2]] + ; CHECK: [[COPY6:%[0-9]+]]:_(s32) = COPY [[USUBE]](s32) + ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP1]](s1) + ; CHECK: $vgpr0 = COPY [[COPY6]](s32) ; CHECK: $vgpr1 = COPY [[ZEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp index 2858dc158cbc23..5d31b6e876b80b 100644 --- a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp @@ -716,6 +716,166 @@ TEST_F(AArch64GISelMITest, WidenSSUBO) { EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; } +TEST_F(AArch64GISelMITest, WidenUADDE) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_UADDE).legalFor({{s16, s16}}); + }); + // Build + // Trunc it to s8. + LLT s8{LLT::scalar(8)}; + LLT s16{LLT::scalar(16)}; + auto MIBTrunc = B.buildTrunc(s8, Copies[0]); + auto CarryIn = B.buildUndef(LLT::scalar(1)); + Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); + auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDE, {s8, CarryReg}, + {MIBTrunc, MIBTrunc, CarryIn}); + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == + LegalizerHelper::LegalizeResult::Legalized); + + const char *CheckStr = R"( + CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC + CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF + CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] + CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] + CHECK: [[UADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ + CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UADDE]] + CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]] + CHECK: G_ICMP intpred(ne), [[UADDE]]:_(s16), [[ZEXT]]:_ + CHECK: G_TRUNC [[UADDE]] + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(AArch64GISelMITest, WidenUSUBE) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder(G_USUBE).legalFor({{s16, s16}}); + }); + // Build + // Trunc it to s8. + LLT s8{LLT::scalar(8)}; + LLT s16{LLT::scalar(16)}; + auto MIBTrunc = B.buildTrunc(s8, Copies[0]); + auto CarryIn = B.buildUndef(LLT::scalar(1)); + Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); + auto MIBUSUBE = B.buildInstr(TargetOpcode::G_USUBE, {s8, CarryReg}, + {MIBTrunc, MIBTrunc, CarryIn}); + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + EXPECT_TRUE(Helper.widenScalar(*MIBUSUBE, 0, s16) == + LegalizerHelper::LegalizeResult::Legalized); + + const char *CheckStr = R"( + CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC + CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF + CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] + CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] + CHECK: [[USUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ + CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[USUBE]] + CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]] + CHECK: G_ICMP intpred(ne), [[USUBE]]:_(s16), [[ZEXT]]:_ + CHECK: G_TRUNC [[USUBE]] + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(AArch64GISelMITest, WidenSADDE) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder({G_SADDE, G_UADDE}).legalFor({{s16, s16}}); + }); + // Build + // Trunc it to s8. + LLT s8{LLT::scalar(8)}; + LLT s16{LLT::scalar(16)}; + auto MIBTrunc = B.buildTrunc(s8, Copies[0]); + auto CarryIn = B.buildUndef(LLT::scalar(1)); + Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); + auto MIBUAddO = B.buildInstr(TargetOpcode::G_SADDE, {s8, CarryReg}, + {MIBTrunc, MIBTrunc, CarryIn}); + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == + LegalizerHelper::LegalizeResult::Legalized); + + const char *CheckStr = R"( + CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC + CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF + CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] + CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] + CHECK: [[SADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ + CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SADDE]] + CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]] + CHECK: G_ICMP intpred(ne), [[SADDE]]:_(s16), [[SEXT]]:_ + CHECK: G_TRUNC [[SADDE]] + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(AArch64GISelMITest, WidenSSUBE) { + setUp(); + if (!TM) + return; + + // Declare your legalization info + DefineLegalizerInfo(A, { + getActionDefinitionsBuilder({G_SSUBE, G_USUBE}).legalFor({{s16, s16}}); + }); + // Build + // Trunc it to s8. + LLT s8{LLT::scalar(8)}; + LLT s16{LLT::scalar(16)}; + auto MIBTrunc = B.buildTrunc(s8, Copies[0]); + auto CarryIn = B.buildUndef(LLT::scalar(1)); + Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); + auto MIBSSUBE = B.buildInstr(TargetOpcode::G_SSUBE, {s8, CarryReg}, + {MIBTrunc, MIBTrunc, CarryIn}); + AInfo Info(MF->getSubtarget()); + DummyGISelObserver Observer; + LegalizerHelper Helper(*MF, Info, Observer, B); + EXPECT_TRUE(Helper.widenScalar(*MIBSSUBE, 0, s16) == + LegalizerHelper::LegalizeResult::Legalized); + + const char *CheckStr = R"( + CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC + CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF + CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] + CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] + CHECK: [[SSUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ + CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SSUBE]] + CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]] + CHECK: G_ICMP intpred(ne), [[SSUBE]]:_(s16), [[SEXT]]:_ + CHECK: G_TRUNC [[SSUBE]] + )"; + + // Check + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + TEST_F(AArch64GISelMITest, FewerElementsAnd) { if (!TM) return;