From 0b71d3972d9138c7482233bc44a9a207634769ef Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 5 Jan 2011 23:06:49 +0000 Subject: [PATCH] Optimize: r1025 = s/zext r1024, 4 r1026 = extract_subreg r1025, 4 to: r1026 = copy r1024 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122925 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 62 ++++++++++++++--------- test/CodeGen/X86/zext-extract_subreg.ll | 60 ++++++++++++++++++++++ 2 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 test/CodeGen/X86/zext-extract_subreg.ll diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 51cbb7f29b4..977cd63844b 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -428,31 +428,47 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, // Figure out the register class to create for the destreg. unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); - const TargetRegisterClass *TRC = MRI->getRegClass(VReg); - const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx); - assert(SRC && "Invalid subregister index in EXTRACT_SUBREG"); - - // Figure out the register class to create for the destreg. - // Note that if we're going to directly use an existing register, - // it must be precisely the required class, and not a subclass - // thereof. - if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { - // Create the reg - assert(SRC && "Couldn't find source register class"); - VRBase = MRI->createVirtualRegister(SRC); - } + MachineInstr *DefMI = MRI->getVRegDef(VReg); + unsigned SrcReg, DstReg, DefSubIdx; + if (DefMI && + TII->isCoalescableExtInstr(*DefMI, SrcReg, DstReg, DefSubIdx) && + SubIdx == DefSubIdx) { + // Optimize these: + // r1025 = s/zext r1024, 4 + // r1026 = extract_subreg r1025, 4 + // to a copy + // r1026 = copy r1024 + const TargetRegisterClass *TRC = MRI->getRegClass(SrcReg); + VRBase = MRI->createVirtualRegister(TRC); + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), + TII->get(TargetOpcode::COPY), VRBase).addReg(SrcReg); + } else { + const TargetRegisterClass *TRC = MRI->getRegClass(VReg); + const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx); + assert(SRC && "Invalid subregister index in EXTRACT_SUBREG"); + + // Figure out the register class to create for the destreg. + // Note that if we're going to directly use an existing register, + // it must be precisely the required class, and not a subclass + // thereof. + if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { + // Create the reg + assert(SRC && "Couldn't find source register class"); + VRBase = MRI->createVirtualRegister(SRC); + } - // Create the extract_subreg machine instruction. - MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), - TII->get(TargetOpcode::COPY), VRBase); + // Create the extract_subreg machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), + TII->get(TargetOpcode::COPY), VRBase); - // Add source, and subreg index - AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap, /*IsDebug=*/false, - IsClone, IsCloned); - assert(TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg()) && - "Cannot yet extract from physregs"); - MI->getOperand(1).setSubReg(SubIdx); - MBB->insert(InsertPos, MI); + // Add source, and subreg index + AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap, /*IsDebug=*/false, + IsClone, IsCloned); + assert(TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg())&& + "Cannot yet extract from physregs"); + MI->getOperand(1).setSubReg(SubIdx); + MBB->insert(InsertPos, MI); + } } else if (Opc == TargetOpcode::INSERT_SUBREG || Opc == TargetOpcode::SUBREG_TO_REG) { SDValue N0 = Node->getOperand(0); diff --git a/test/CodeGen/X86/zext-extract_subreg.ll b/test/CodeGen/X86/zext-extract_subreg.ll new file mode 100644 index 00000000000..e61e8805a2f --- /dev/null +++ b/test/CodeGen/X86/zext-extract_subreg.ll @@ -0,0 +1,60 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s + +define void @t() nounwind ssp { +; CHECK: t: +entry: + br i1 undef, label %return, label %if.end.i + +if.end.i: ; preds = %entry + %tmp7.i = load i32* undef, align 4, !tbaa !0 + br i1 undef, label %return, label %if.end + +if.end: ; preds = %if.end.i +; CHECK: %if.end +; CHECK: movl (%{{.*}}), [[REG:%[a-z]+]] +; CHECK-NOT: movl [[REG]], [[REG]] +; CHECK-NEXT: xorb + %tmp138 = select i1 undef, i32 0, i32 %tmp7.i + %tmp867 = zext i32 %tmp138 to i64 + br label %while.cond + +while.cond: ; preds = %while.body, %if.end + %tmp869 = sub i64 %tmp867, 0 + %scale2.0 = trunc i64 %tmp869 to i32 + %cmp149 = icmp eq i32 %scale2.0, 0 + br i1 %cmp149, label %while.end, label %land.rhs + +land.rhs: ; preds = %while.cond + br i1 undef, label %while.body, label %while.end + +while.body: ; preds = %land.rhs + br label %while.cond + +while.end: ; preds = %land.rhs, %while.cond + br i1 undef, label %cond.false205, label %cond.true190 + +cond.true190: ; preds = %while.end + br i1 undef, label %cond.false242, label %cond.true225 + +cond.false205: ; preds = %while.end + unreachable + +cond.true225: ; preds = %cond.true190 + br i1 undef, label %cond.false280, label %cond.true271 + +cond.false242: ; preds = %cond.true190 + unreachable + +cond.true271: ; preds = %cond.true225 + unreachable + +cond.false280: ; preds = %cond.true225 + unreachable + +return: ; preds = %if.end.i, %entry + ret void +} + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} -- 2.34.1