From: Evan Cheng Date: Tue, 31 Mar 2009 20:42:45 +0000 (+0000) Subject: Throttle back "fold select into operand" transformation. InstCombine should not gener... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=de62192843c90189fbb21145437b085848140122;p=oota-llvm.git Throttle back "fold select into operand" transformation. InstCombine should not generate selects of two constants unless they are selects of 0 and 1. e.g. define i32 @t1(i32 %c, i32 %x) nounwind { %t1 = icmp eq i32 %c, 0 %t2 = lshr i32 %x, 18 %t3 = select i1 %t1, i32 %t2, i32 %x ret i32 %t3 } was turned into define i32 @t2(i32 %c, i32 %x) nounwind { %t1 = icmp eq i32 %c, 0 %t2 = select i1 %t1, i32 18, i32 0 %t3 = lshr i32 %x, %t2 ret i32 %t3 } For most targets, that means materializing two constants and then a select. e.g. On x86-64 movl %esi, %eax shrl $18, %eax testl %edi, %edi cmovne %esi, %eax ret => xorl %eax, %eax testl %edi, %edi movl $18, %ecx cmovne %eax, %ecx movl %esi, %eax shrl %cl, %eax ret Also, the optimizer and codegen can reason about shl / and / add, etc. by a constant. This optimization will hinder optimizations using ComputeMaskedBits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68142 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 1f80444632d..adab875f953 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -223,6 +223,7 @@ namespace { Instruction *visitBitCast(BitCastInst &CI); Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI, Instruction *FI); + Instruction *FoldSelectIntoOp(SelectInst &SI, Value*, Value*); Instruction *visitSelectInst(SelectInst &SI); Instruction *visitSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI); Instruction *visitCallInst(CallInst &CI); @@ -8836,6 +8837,83 @@ Instruction *InstCombiner::FoldSelectOpOp(SelectInst &SI, Instruction *TI, return 0; } +static bool isSelect01(Constant *C1, Constant *C2) { + ConstantInt *C1I = dyn_cast(C1); + if (!C1I) + return false; + ConstantInt *C2I = dyn_cast(C2); + if (!C2I) + return false; + return (C1I->isZero() || C1I->isOne()) && (C2I->isZero() || C2I->isOne()); +} + +/// FoldSelectIntoOp - Try fold the select into one of the operands to +/// facilitate further optimization. +Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, + Value *FalseVal) { + // See the comment above GetSelectFoldableOperands for a description of the + // transformation we are doing here. + if (Instruction *TVI = dyn_cast(TrueVal)) { + if (TVI->hasOneUse() && TVI->getNumOperands() == 2 && + !isa(FalseVal)) { + if (unsigned SFO = GetSelectFoldableOperands(TVI)) { + unsigned OpToFold = 0; + if ((SFO & 1) && FalseVal == TVI->getOperand(0)) { + OpToFold = 1; + } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) { + OpToFold = 2; + } + + if (OpToFold) { + Constant *C = GetSelectFoldableConstant(TVI); + Value *OOp = TVI->getOperand(2-OpToFold); + // Avoid creating select between 2 constants unless it's selecting + // between 0 and 1. + if (!isa(OOp) || isSelect01(C, cast(OOp))) { + Instruction *NewSel = SelectInst::Create(SI.getCondition(), OOp, C); + InsertNewInstBefore(NewSel, SI); + NewSel->takeName(TVI); + if (BinaryOperator *BO = dyn_cast(TVI)) + return BinaryOperator::Create(BO->getOpcode(), FalseVal, NewSel); + assert(0 && "Unknown instruction!!"); + } + } + } + } + } + + if (Instruction *FVI = dyn_cast(FalseVal)) { + if (FVI->hasOneUse() && FVI->getNumOperands() == 2 && + !isa(TrueVal)) { + if (unsigned SFO = GetSelectFoldableOperands(FVI)) { + unsigned OpToFold = 0; + if ((SFO & 1) && TrueVal == FVI->getOperand(0)) { + OpToFold = 1; + } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) { + OpToFold = 2; + } + + if (OpToFold) { + Constant *C = GetSelectFoldableConstant(FVI); + Value *OOp = FVI->getOperand(2-OpToFold); + // Avoid creating select between 2 constants unless it's selecting + // between 0 and 1. + if (!isa(OOp) || isSelect01(C, cast(OOp))) { + Instruction *NewSel = SelectInst::Create(SI.getCondition(), C, OOp); + InsertNewInstBefore(NewSel, SI); + NewSel->takeName(FVI); + if (BinaryOperator *BO = dyn_cast(FVI)) + return BinaryOperator::Create(BO->getOpcode(), TrueVal, NewSel); + assert(0 && "Unknown instruction!!"); + } + } + } + } + } + + return 0; +} + /// visitSelectInstWithICmp - Visit a SelectInst that has an /// ICmpInst as its first operand. /// @@ -9181,58 +9259,9 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { // See if we can fold the select into one of our operands. if (SI.getType()->isInteger()) { - // See the comment above GetSelectFoldableOperands for a description of the - // transformation we are doing here. - if (Instruction *TVI = dyn_cast(TrueVal)) - if (TVI->hasOneUse() && TVI->getNumOperands() == 2 && - !isa(FalseVal)) - if (unsigned SFO = GetSelectFoldableOperands(TVI)) { - unsigned OpToFold = 0; - if ((SFO & 1) && FalseVal == TVI->getOperand(0)) { - OpToFold = 1; - } else if ((SFO & 2) && FalseVal == TVI->getOperand(1)) { - OpToFold = 2; - } - - if (OpToFold) { - Constant *C = GetSelectFoldableConstant(TVI); - Instruction *NewSel = - SelectInst::Create(SI.getCondition(), - TVI->getOperand(2-OpToFold), C); - InsertNewInstBefore(NewSel, SI); - NewSel->takeName(TVI); - if (BinaryOperator *BO = dyn_cast(TVI)) - return BinaryOperator::Create(BO->getOpcode(), FalseVal, NewSel); - else { - assert(0 && "Unknown instruction!!"); - } - } - } - - if (Instruction *FVI = dyn_cast(FalseVal)) - if (FVI->hasOneUse() && FVI->getNumOperands() == 2 && - !isa(TrueVal)) - if (unsigned SFO = GetSelectFoldableOperands(FVI)) { - unsigned OpToFold = 0; - if ((SFO & 1) && TrueVal == FVI->getOperand(0)) { - OpToFold = 1; - } else if ((SFO & 2) && TrueVal == FVI->getOperand(1)) { - OpToFold = 2; - } - - if (OpToFold) { - Constant *C = GetSelectFoldableConstant(FVI); - Instruction *NewSel = - SelectInst::Create(SI.getCondition(), C, - FVI->getOperand(2-OpToFold)); - InsertNewInstBefore(NewSel, SI); - NewSel->takeName(FVI); - if (BinaryOperator *BO = dyn_cast(FVI)) - return BinaryOperator::Create(BO->getOpcode(), TrueVal, NewSel); - else - assert(0 && "Unknown instruction!!"); - } - } + Instruction *FoldI = FoldSelectIntoOp(SI, TrueVal, FalseVal); + if (FoldI) + return FoldI; } if (BinaryOperator::isNot(CondVal)) { diff --git a/test/Transforms/InstCombine/select-2.ll b/test/Transforms/InstCombine/select-2.ll new file mode 100644 index 00000000000..4621f6e152a --- /dev/null +++ b/test/Transforms/InstCombine/select-2.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep select | count 2 + +; Make sure instcombine don't fold select into operands. We don't want to emit +; select of two integers unless it's selecting 0 / 1. + +define i32 @t1(i32 %c, i32 %x) nounwind { + %t1 = icmp eq i32 %c, 0 + %t2 = lshr i32 %x, 18 + %t3 = select i1 %t1, i32 %t2, i32 %x + ret i32 %t3 +} + +define i32 @t2(i32 %c, i32 %x) nounwind { + %t1 = icmp eq i32 %c, 0 + %t2 = and i32 %x, 18 + %t3 = select i1 %t1, i32 %t2, i32 %x + ret i32 %t3 +}