OSDN Git Service

[GISel]: Add legalization support for Widening UADDO/USUBO
authorAditya Nandakumar <aditya_nandakumar@apple.com>
Wed, 29 Aug 2018 03:17:08 +0000 (03:17 +0000)
committerAditya Nandakumar <aditya_nandakumar@apple.com>
Wed, 29 Aug 2018 03:17:08 +0000 (03:17 +0000)
https://reviews.llvm.org/D51384

Added code in LegalizerHelper to widen UADDO/USUBO along with unit
tests.

Reviewed by volkan.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@340892 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/GlobalISel/LegalizerHelper.cpp
unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp

index 4990673..ff2e61c 100644 (file)
@@ -619,6 +619,32 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
   switch (MI.getOpcode()) {
   default:
     return UnableToLegalize;
+  case TargetOpcode::G_UADDO:
+  case TargetOpcode::G_USUBO: {
+    if (TypeIdx == 1)
+      return UnableToLegalize; // TODO
+    auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, WideTy,
+                                         MI.getOperand(2).getReg());
+    auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, WideTy,
+                                         MI.getOperand(3).getReg());
+    unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
+                          ? TargetOpcode::G_ADD
+                          : TargetOpcode::G_SUB;
+    // Do the arithmetic in the larger type.
+    auto NewOp = MIRBuilder.buildInstr(Opcode, WideTy, LHSZext, RHSZext);
+    LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
+    APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
+    auto AndOp = MIRBuilder.buildInstr(
+        TargetOpcode::G_AND, WideTy, NewOp,
+        MIRBuilder.buildConstant(WideTy, Mask.getZExtValue()));
+    // There is no overflow if the AndOp is the same as NewOp.
+    MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
+                         AndOp);
+    // Now trunc the NewOp to the original result.
+    MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
+    MI.eraseFromParent();
+    return Legalized;
+  }
   case TargetOpcode::G_CTTZ:
   case TargetOpcode::G_CTTZ_ZERO_UNDEF:
   case TargetOpcode::G_CTLZ:
index 65d0d73..0cc989b 100644 (file)
@@ -342,4 +342,79 @@ TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ) {
   // Check
   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
 }
+// UADDO widening.
+TEST_F(LegalizerHelperTest, WidenUADDO) {
+  if (!TM)
+    return;
+
+  // Declare your legalization info
+  DefineLegalizerInfo(A,
+                      { getActionDefinitionsBuilder(G_ADD).legalFor({s16}); });
+  // Build
+  // Trunc it to s8.
+  LLT s8{LLT::scalar(8)};
+  LLT s16{LLT::scalar(16)};
+  auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+  unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
+  auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDO, s8)
+                      .addDef(CarryReg)
+                      .addUse(MIBTrunc->getOperand(0).getReg())
+                      .addUse(MIBTrunc->getOperand(0).getReg());
+  AInfo Info(MF->getSubtarget());
+  LegalizerHelper Helper(*MF, Info);
+  ASSERT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
+              LegalizerHelper::LegalizeResult::Legalized);
+
+  auto CheckStr = R"(
+  CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+  CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+  CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+  CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
+  CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
+  CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
+  CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
+  CHECK: G_TRUNC [[ADD]]
+  )";
+
+  // Check
+  ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
+
+// USUBO widening.
+TEST_F(LegalizerHelperTest, WidenUSUBO) {
+  if (!TM)
+    return;
+
+  // Declare your legalization info
+  DefineLegalizerInfo(A,
+                      { getActionDefinitionsBuilder(G_SUB).legalFor({s16}); });
+  // Build
+  // Trunc it to s8.
+  LLT s8{LLT::scalar(8)};
+  LLT s16{LLT::scalar(16)};
+  auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
+  unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
+  auto MIBUSUBO = B.buildInstr(TargetOpcode::G_USUBO, s8)
+                      .addDef(CarryReg)
+                      .addUse(MIBTrunc->getOperand(0).getReg())
+                      .addUse(MIBTrunc->getOperand(0).getReg());
+  AInfo Info(MF->getSubtarget());
+  LegalizerHelper Helper(*MF, Info);
+  ASSERT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
+              LegalizerHelper::LegalizeResult::Legalized);
+
+  auto CheckStr = R"(
+  CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
+  CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+  CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
+  CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
+  CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
+  CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
+  CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
+  CHECK: G_TRUNC [[SUB]]
+  )";
+
+  // Check
+  ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
+}
 } // namespace