forked from OSchip/llvm-project
[Legalizer] Add support for G_OR NarrowScalar.
Legalize bitwise OR: A = BinOp<Ty> B, C into: B1, ..., BN = G_UNMERGE_VALUES B C1, ..., CN = G_UNMERGE_VALUES C A1 = BinOp<Ty/N> B1, C2 ... AN = BinOp<Ty/N> BN, CN A = G_MERGE_VALUES A1, ..., AN llvm-svn: 314760
This commit is contained in:
parent
60ee7e302a
commit
c2f3cea608
|
@ -396,6 +396,50 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
|
|||
MI.eraseFromParent();
|
||||
return Legalized;
|
||||
}
|
||||
case TargetOpcode::G_OR: {
|
||||
// Legalize bitwise operation:
|
||||
// A = BinOp<Ty> B, C
|
||||
// into:
|
||||
// B1, ..., BN = G_UNMERGE_VALUES B
|
||||
// C1, ..., CN = G_UNMERGE_VALUES C
|
||||
// A1 = BinOp<Ty/N> B1, C2
|
||||
// ...
|
||||
// AN = BinOp<Ty/N> 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<unsigned, 2> DstRegs;
|
||||
// List the registers where the first argument will be split.
|
||||
SmallVector<unsigned, 2> SrcsReg1;
|
||||
// List the registers where the second argument will be split.
|
||||
SmallVector<unsigned, 2> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
...
|
||||
|
|
Loading…
Reference in New Issue