From 69c337e7d03db7f274543bedb8e9e8d1353c29c5 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Tue, 3 Oct 2017 04:53:56 +0000 Subject: [PATCH] [Legalizer] Add support for G_OR NarrowScalar. Legalize bitwise OR: A = BinOp B, C into: B1, ..., BN = G_UNMERGE_VALUES B C1, ..., CN = G_UNMERGE_VALUES C A1 = BinOp B1, C2 ... AN = BinOp BN, CN A = G_MERGE_VALUES A1, ..., AN llvm-svn: 314760 --- lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 44 ++++++++++++++ lib/CodeGen/GlobalISel/LegalizerInfo.cpp | 1 + .../AArch64/GlobalISel/legalize-or.mir | 59 +++++++++++++++---- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index a70e46e67df..cd6684fbb4e 100644 --- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -396,6 +396,50 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, MI.eraseFromParent(); return Legalized; } + case TargetOpcode::G_OR: { + // Legalize bitwise operation: + // A = BinOp B, C + // into: + // B1, ..., BN = G_UNMERGE_VALUES B + // C1, ..., CN = G_UNMERGE_VALUES C + // A1 = BinOp B1, C2 + // ... + // AN = BinOp BN, CN + // A = G_MERGE_VALUES A1, ..., AN + unsigned NarrowSize = NarrowTy.getSizeInBits(); + int NumParts = + MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; + + // List the registers where the destination will be scattered. + SmallVector DstRegs; + // List the registers where the first argument will be split. + SmallVector SrcsReg1; + // List the registers where the second argument will be split. + SmallVector SrcsReg2; + // Create all the temporary registers. + for (int i = 0; i < NumParts; ++i) { + unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); + unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy); + unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy); + + DstRegs.push_back(DstReg); + SrcsReg1.push_back(SrcReg1); + SrcsReg2.push_back(SrcReg2); + } + // Explode the big arguments into smaller chunks. + MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg()); + MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg()); + + // Do the operation on each small part. + for (int i = 0; i < NumParts; ++i) + MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]); + + // Gather the destination registers into the final destination. + unsigned DstReg = MI.getOperand(0).getReg(); + MIRBuilder.buildMerge(DstReg, DstRegs); + MI.eraseFromParent(); + return Legalized; + } } } diff --git a/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/lib/CodeGen/GlobalISel/LegalizerInfo.cpp index 76917aa9660..4fc4fa7d3eb 100644 --- a/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -48,6 +48,7 @@ LegalizerInfo::LegalizerInfo() { DefaultActions[TargetOpcode::G_ADD] = NarrowScalar; DefaultActions[TargetOpcode::G_LOAD] = NarrowScalar; DefaultActions[TargetOpcode::G_STORE] = NarrowScalar; + DefaultActions[TargetOpcode::G_OR] = NarrowScalar; DefaultActions[TargetOpcode::G_BRCOND] = WidenScalar; DefaultActions[TargetOpcode::G_INSERT] = NarrowScalar; diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-or.mir b/test/CodeGen/AArch64/GlobalISel/legalize-or.mir index 4d1a88871c9..ac682c33c35 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-or.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-or.mir @@ -1,13 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s - ---- | - target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" - target triple = "aarch64--" - define void @test_scalar_or_small() { - entry: - ret void - } -... +# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- name: test_scalar_or_small @@ -19,7 +10,7 @@ registers: - { id: 4, class: _ } - { id: 5, class: _ } body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_or_small ; CHECK: [[OP0:%.*]](s32) = G_TRUNC %0 @@ -35,3 +26,49 @@ body: | %5(s64) = G_ANYEXT %2 %x0 = COPY %5 ... + +--- +name: test_big_scalar_power_of_2 +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } + - { id: 5, class: _ } + - { id: 6, class: _ } + - { id: 7, class: _ } + - { id: 8, class: _ } +body: | + bb.0: + liveins: %x0, %x1, %x2, %x3 + ; CHECK-LABEL: name: test_big_scalar_power_of_2 + ; CHECK: [[OP0_0:%.*]](s64) = COPY %x0 + ; CHECK-NEXT: [[OP0_1:%.*]](s64) = COPY %x1 + ; CHECK-NEXT: [[OP1_0:%.*]](s64) = COPY %x2 + ; CHECK-NEXT: [[OP1_1:%.*]](s64) = COPY %x3 + ; CHECK-NEXT: [[RES_0:%.*]](s64) = G_OR [[OP0_0]], [[OP1_0]] + ; CHECK-NEXT: [[RES_1:%.*]](s64) = G_OR [[OP0_1]], [[OP1_1]] + ; We have a temporary G_MERGE_VALUES in the legalizer + ; that gets cleaned up with the G_UNMERGE_VALUES. + ; Thus, + ; tmp = G_MERGE_VALUES [[RES_0]], [[RES_1]] + ; %7, %8 = G_UNMERGE_VALUES tmp + ; %x0 = COPY %7 + ; %x1 = COPY %8 + ; translates into + ; CHECK-NEXT: %x0 = COPY [[RES_0]] + ; CHECK-NEXT: %x1 = COPY [[RES_1]] + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = COPY %x2 + %3(s64) = COPY %x3 + %4(s128) = G_MERGE_VALUES %0, %1 + %5(s128) = G_MERGE_VALUES %2, %3 + %6(s128) = G_OR %4, %5 + %7(s64), %8(s64) = G_UNMERGE_VALUES %6 + %x0 = COPY %7 + %x1 = COPY %8 + RET_ReallyLR implicit %x0, implicit %x1 +...