From 23d3243e620064c69e4e6308156208f3205342c1 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 5 May 2011 16:53:34 +0000 Subject: [PATCH] Avoid extra vreg copies for arguments passed in registers. Specifically, this can make MachineCSE more effective in some cases (especially in small functions). PR8361 / part of rdar://problem/8259436 . git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130928 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../SelectionDAG/FunctionLoweringInfo.cpp | 26 --------- .../SelectionDAG/SelectionDAGBuilder.cpp | 54 +++++++++++++++---- .../X86/2010-06-25-CoalescerSubRegDefDead.ll | 2 +- test/CodeGen/X86/cmp-redundant.ll | 21 ++++++++ 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index d8a5770d36c..a1e8254189f 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -54,25 +54,6 @@ static bool isUsedOutsideOfDefiningBlock(const Instruction *I) { return false; } -/// isOnlyUsedInEntryBlock - If the specified argument is only used in the -/// entry block, return true. This includes arguments used by switches, since -/// the switch may expand into multiple basic blocks. -static bool isOnlyUsedInEntryBlock(const Argument *A, bool EnableFastISel) { - // With FastISel active, we may be splitting blocks, so force creation - // of virtual registers for all non-dead arguments. - if (EnableFastISel) - return A->use_empty(); - - const BasicBlock *Entry = A->getParent()->begin(); - for (Value::const_use_iterator UI = A->use_begin(), E = A->use_end(); - UI != E; ++UI) { - const User *U = *UI; - if (cast(U)->getParent() != Entry || isa(U)) - return false; // Use not in entry block. - } - return true; -} - FunctionLoweringInfo::FunctionLoweringInfo(const TargetLowering &tli) : TLI(tli) { } @@ -89,13 +70,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) { CanLowerReturn = TLI.CanLowerReturn(Fn->getCallingConv(), Fn->isVarArg(), Outs, Fn->getContext()); - // Create a vreg for each argument register that is not dead and is used - // outside of the entry block for the function. - for (Function::const_arg_iterator AI = Fn->arg_begin(), E = Fn->arg_end(); - AI != E; ++AI) - if (!isOnlyUsedInEntryBlock(AI, EnableFastISel)) - InitializeRegForValue(AI); - // Initialize the mapping of values to registers. This is only set up for // instruction values that are used outside of the block that defines // them. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index b02a7b66c49..c69be7bb51c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6232,6 +6232,25 @@ SelectionDAGBuilder::CopyValueToVirtualRegister(const Value *V, unsigned Reg) { #include "llvm/CodeGen/SelectionDAGISel.h" +/// isOnlyUsedInEntryBlock - If the specified argument is only used in the +/// entry block, return true. This includes arguments used by switches, since +/// the switch may expand into multiple basic blocks. +static bool isOnlyUsedInEntryBlock(const Argument *A) { + // With FastISel active, we may be splitting blocks, so force creation + // of virtual registers for all non-dead arguments. + if (EnableFastISel) + return A->use_empty(); + + const BasicBlock *Entry = A->getParent()->begin(); + for (Value::const_use_iterator UI = A->use_begin(), E = A->use_end(); + UI != E; ++UI) { + const User *U = *UI; + if (cast(U)->getParent() != Entry || isa(U)) + return false; // Use not in entry block. + } + return true; +} + void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { // If this is the entry block, emit arguments. const Function &F = *LLVMBB->getParent(); @@ -6375,8 +6394,8 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { if (I->use_empty() && NumValues) SDB->setUnusedArgValue(I, InVals[i]); - for (unsigned Value = 0; Value != NumValues; ++Value) { - EVT VT = ValueVTs[Value]; + for (unsigned Val = 0; Val != NumValues; ++Val) { + EVT VT = ValueVTs[Val]; EVT PartVT = TLI.getRegisterType(*CurDAG->getContext(), VT); unsigned NumParts = TLI.getNumRegisters(*CurDAG->getContext(), VT); @@ -6395,21 +6414,34 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { i += NumParts; } + // We don't need to do anything else for unused arguments. + if (ArgValues.empty()) + continue; + // Note down frame index for byval arguments. - if (I->hasByValAttr() && !ArgValues.empty()) + if (I->hasByValAttr()) if (FrameIndexSDNode *FI = dyn_cast(ArgValues[0].getNode())) FuncInfo->setByValArgumentFrameIndex(I, FI->getIndex()); - if (!I->use_empty()) { - SDValue Res; - if (!ArgValues.empty()) - Res = DAG.getMergeValues(&ArgValues[0], NumValues, - SDB->getCurDebugLoc()); - SDB->setValue(I, Res); + SDValue Res = DAG.getMergeValues(&ArgValues[0], NumValues, + SDB->getCurDebugLoc()); + SDB->setValue(I, Res); - // If this argument is live outside of the entry block, insert a copy from - // wherever we got it to the vreg that other BB's will reference it as. + // If this argument is live outside of the entry block, insert a copy from + // wherever we got it to the vreg that other BB's will reference it as. + if (Res.getOpcode() == ISD::CopyFromReg) { + // If we can, though, try to skip creating an unnecessary vreg. + // FIXME: This isn't very clean... it would be nice to make this more + // general. + unsigned Reg = cast(Res.getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + FuncInfo->ValueMap[I] = Reg; + continue; + } + } + if (!isOnlyUsedInEntryBlock(I)) { + FuncInfo->InitializeRegForValue(I); SDB->CopyToExportRegsIfNeeded(I); } } diff --git a/test/CodeGen/X86/2010-06-25-CoalescerSubRegDefDead.ll b/test/CodeGen/X86/2010-06-25-CoalescerSubRegDefDead.ll index 6db3ce1f42c..bb1db598d41 100644 --- a/test/CodeGen/X86/2010-06-25-CoalescerSubRegDefDead.ll +++ b/test/CodeGen/X86/2010-06-25-CoalescerSubRegDefDead.ll @@ -22,7 +22,7 @@ bb: ; it is. ; ; CHECK: # %bb -; CHECK: addq $64036, %rdi +; CHECK: leaq 64036(%rdx), %rdi ; CHECK: rep;stosl %tmp5 = bitcast i32* %tmp4 to i8* diff --git a/test/CodeGen/X86/cmp-redundant.ll b/test/CodeGen/X86/cmp-redundant.ll index d30ea3edd68..39d3440fbac 100644 --- a/test/CodeGen/X86/cmp-redundant.ll +++ b/test/CodeGen/X86/cmp-redundant.ll @@ -9,6 +9,27 @@ entry: ; CHECK: cmp: ; CHECK: cmpl ; CHECK: jg + +if.end: ; preds = %entry +; CHECK-NOT: cmpl +; CHECK: cmov + %cmp4 = icmp slt i32 %a, %b + %. = select i1 %cmp4, i32 2, i32 111 + br label %return + +return: ; preds = %if.end, %entry + %retval.0 = phi i32 [ 1, %entry ], [ %., %if.end ] + ret i32 %retval.0 +} + +define i32 @cmp2(i32 %a, i32 %b) nounwind readnone ssp { +entry: + %cmp = icmp sgt i32 %a, %b + br i1 %cmp, label %return, label %if.end +; CHECK: cmp2: +; CHECK: cmpl +; CHECK: jg + if.end: ; preds = %entry ; CHECK-NOT: cmpl ; CHECK: cmov