void Legalizer::init(MachineFunction &MF) {
}
-bool Legalizer::combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI,
- const TargetInstrInfo &TII) {
- bool Changed = false;
- if (MI.getOpcode() != TargetOpcode::G_EXTRACT)
- return Changed;
-
- unsigned NumDefs = (MI.getNumOperands() - 1) / 2;
- unsigned SrcReg = MI.getOperand(NumDefs).getReg();
- MachineInstr &SeqI = *MRI.def_instr_begin(SrcReg);
- if (SeqI.getOpcode() != TargetOpcode::G_SEQUENCE)
- return Changed;
-
- unsigned NumSeqSrcs = (SeqI.getNumOperands() - 1) / 2;
- bool AllDefsReplaced = true;
-
- // Try to match each register extracted with a corresponding insertion formed
- // by the G_SEQUENCE.
- for (unsigned Idx = 0, SeqIdx = 0; Idx < NumDefs; ++Idx) {
- MachineOperand &ExtractMO = MI.getOperand(Idx);
- assert(ExtractMO.isReg() && ExtractMO.isDef() &&
- "unexpected extract operand");
-
- unsigned ExtractReg = ExtractMO.getReg();
- unsigned ExtractPos = MI.getOperand(NumDefs + Idx + 1).getImm();
-
- while (SeqIdx < NumSeqSrcs &&
- SeqI.getOperand(2 * SeqIdx + 2).getImm() < ExtractPos)
- ++SeqIdx;
-
- if (SeqIdx == NumSeqSrcs) {
- AllDefsReplaced = false;
- continue;
- }
-
- unsigned OrigReg = SeqI.getOperand(2 * SeqIdx + 1).getReg();
- if (SeqI.getOperand(2 * SeqIdx + 2).getImm() != ExtractPos ||
- MRI.getType(OrigReg) != MRI.getType(ExtractReg)) {
- AllDefsReplaced = false;
- continue;
- }
-
- assert(!TargetRegisterInfo::isPhysicalRegister(OrigReg) &&
- "unexpected physical register in G_SEQUENCE");
-
- // Finally we can replace the uses.
- MRI.replaceRegWith(ExtractReg, OrigReg);
- }
-
- if (AllDefsReplaced) {
- // If SeqI was the next instruction in the BB and we removed it, we'd break
- // the outer iteration.
- assert(std::next(MachineBasicBlock::iterator(MI)) != SeqI &&
- "G_SEQUENCE does not dominate G_EXTRACT");
-
- MI.eraseFromParent();
-
- if (MRI.use_empty(SrcReg))
- SeqI.eraseFromParent();
- Changed = true;
- }
-
- return Changed;
-}
-
bool Legalizer::combineMerges(MachineInstr &MI, MachineRegisterInfo &MRI,
const TargetInstrInfo &TII,
MachineIRBuilder &MIRBuilder) {
// Get the next Instruction before we try to legalize, because there's a
// good chance MI will be deleted.
NextMI = std::next(MI);
-
- // combineExtracts erases MI.
- if (combineExtracts(*MI, MRI, TII)) {
- Changed = true;
- continue;
- }
Changed |= combineMerges(*MI, MRI, TII, Helper.MIRBuilder);
}
}
--- |
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--"
- define void @test_combines_1() { ret void }
define void @test_combines_2() { ret void }
define void @test_combines_3() { ret void }
define void @test_combines_4() { ret void }
...
---
-name: test_combines_1
-body: |
- bb.0:
- liveins: %w0
-
- %0:_(s32) = COPY %w0
- %1:_(s8) = G_TRUNC %0
-
- ; Only one of these extracts can be eliminated, the offsets don't match
- ; properly in the other cases.
- ; CHECK-LABEL: name: test_combines_1
- ; CHECK: %2(s32) = G_SEQUENCE %1(s8), 1
- ; CHECK: %3(s8) = G_EXTRACT %2(s32), 0
- ; CHECK-NOT: G_EXTRACT
- ; CHECK: %5(s8) = G_EXTRACT %2(s32), 2
- ; CHECK: %6(s32) = G_ZEXT %1(s8)
-
- %2:_(s32) = G_SEQUENCE %1, 1
- %3:_(s8) = G_EXTRACT %2, 0
- %4:_(s8) = G_EXTRACT %2, 1
- %5:_(s8) = G_EXTRACT %2, 2
- %6:_(s32) = G_ZEXT %4
-...
-
----
name: test_combines_2
body: |
bb.0:
; Similarly, here the types don't match.
; CHECK-LABEL: name: test_combines_2
- ; CHECK: %2(s64) = G_SEQUENCE %0(s32), 0, %1(s32), 32
+ ; CHECK: %2(s64) = G_MERGE_VALUES %0(s32), %1(s32)
; CHECK: %3(s1) = G_EXTRACT %2(s64), 0
; CHECK: %4(s64) = G_EXTRACT %2(s64), 0
%1:_(s32) = G_ADD %0, %0
- %2:_(s64) = G_SEQUENCE %0, 0, %1, 32
+ %2:_(s64) = G_MERGE_VALUES %0, %1
%3:_(s1) = G_EXTRACT %2, 0
%4:_(s64) = G_EXTRACT %2, 0
...
; CHECK-NOT: G_EXTRACT
; CHECK: %5(s32) = G_ADD %0, %1
%1:_(s32) = G_ADD %0, %0
- %2:_(s64) = G_SEQUENCE %0, 0, %1, 32
- %3:_(s32) = G_EXTRACT %2, 0
- %4:_(s32) = G_EXTRACT %2, 32
+ %2:_(s64) = G_MERGE_VALUES %0, %1
+ %3:_(s32), %4:_(s32) = G_UNMERGE_VALUES %2
%5:_(s32) = G_ADD %3, %4
...
; CHECK-LABEL: name: test_combines_4
; CHECK: %2(<2 x s32>) = G_EXTRACT %1(s128), 0
; CHECK: %3(<2 x s32>) = G_ADD %2, %2
- %1:_(s128) = G_SEQUENCE %0, 0, %0, 64
+ %1:_(s128) = G_MERGE_VALUES %0, %0
%2:_(<2 x s32>) = G_EXTRACT %1, 0
%3:_(<2 x s32>) = G_ADD %2, %2
...
%0:_(s32) = COPY %w0
; CHECK-LABEL: name: test_combines_5
- ; CHECK-NOT: G_SEQUENCE
+ ; CHECK-NOT: G_MERGE_VALUES
; CHECK-NOT: G_EXTRACT
; CHECK: %5(s32) = G_ADD %0, %1
%1:_(s32) = G_ADD %0, %0
- %2:_(s64) = G_SEQUENCE %0, 0, %1, 32
- %3:_(s32) = G_EXTRACT %2, 0
- %4:_(s32) = G_EXTRACT %2, 32
+ %2:_(s64) = G_MERGE_VALUES %0, %1
+ %3:_(s32), %4:_(s32) = G_UNMERGE_VALUES %2
%5:_(s32) = G_ADD %3, %4
...
%0:_(s32) = COPY %w0
; Check that we replace all the uses of a G_EXTRACT.
- ; CHECK-NOT: G_SEQUENCE
+ ; CHECK-NOT: G_MERGE_VALUES
; CHECK-NOT: G_EXTRACT
; CHECK: %3(s32) = G_MUL %0, %0
; CHECK: %4(s32) = G_ADD %0, %3
- %1:_(s32) = G_SEQUENCE %0, 0
- %2:_(s32) = G_EXTRACT %1, 0
+ %1:_(s32) = G_MERGE_VALUES %0
+ %2:_(s32) = G_UNMERGE_VALUES %1
%3:_(s32) = G_MUL %2, %2
%4:_(s32) = G_ADD %2, %3
...