[llvm] r218721 - [InstCombine] Optimize icmp-select-icmp
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Wed Oct 1 02:31:20 PDT 2014
I've started a clobber build just in case. If the issue is still
there, I'll revert.
On Wed, Oct 1, 2014 at 1:17 PM, Chandler Carruth <chandlerc at google.com> wrote:
> Evgeniy, if this is still breaking the bot, let's just revert it. What with
> timezones it'll be a while before Gerolf can likely look at it again and I
> think its more important to have the bots green in the interim.
>
> On Wed, Oct 1, 2014 at 2:14 AM, Evgeniy Stepanov <eugeni.stepanov at gmail.com>
> wrote:
>>
>> Does not look like it helped:
>> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/13128
>>
>>
>> On Wed, Oct 1, 2014 at 8:16 AM, Chandler Carruth <chandlerc at google.com>
>> wrote:
>> > Awesome, thanks!
>> >
>> > On Sep 30, 2014 8:37 PM, "Gerolf Hoflehner" <ghoflehner at apple.com>
>> > wrote:
>> >>
>> >> The fix is
>> >>
>> >> Committed revision 218735.
>> >>
>> >>
>> >> On Sep 30, 2014, at 8:30 PM, Chandler Carruth <chandlerc at google.com>
>> >> wrote:
>> >>
>> >> It's already been 3 hours. Please do one quickly, I'm worried about the
>> >> number of commits going in after this that aren't getting sanitizer
>> >> coverage.
>> >>
>> >> On Tue, Sep 30, 2014 at 8:21 PM, Gerolf Hoflehner
>> >> <ghoflehner at apple.com>
>> >> wrote:
>> >>>
>> >>> Ok, thanks! I’ll provide a fix or back out shortly.
>> >>>
>> >>>
>> >>> On Sep 30, 2014, at 6:13 PM, Chandler Carruth <chandlerc at google.com>
>> >>> wrote:
>> >>>
>> >>> FYI, this is assert failing on build bots:
>> >>> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/13123
>> >>>
>> >>> On Tue, Sep 30, 2014 at 5:13 PM, Gerolf Hoflehner
>> >>> <ghoflehner at apple.com>
>> >>> wrote:
>> >>>>
>> >>>> Author: ghoflehner
>> >>>> Date: Tue Sep 30 19:13:22 2014
>> >>>> New Revision: 218721
>> >>>>
>> >>>> URL: http://llvm.org/viewvc/llvm-project?rev=218721&view=rev
>> >>>> Log:
>> >>>> [InstCombine] Optimize icmp-select-icmp
>> >>>>
>> >>>> In special cases select instructions can be eliminated by
>> >>>> replacing them with a cheaper bitwise operation even when the
>> >>>> select result is used outside its home block. The instances
>> >>>> implemented
>> >>>> are patterns like
>> >>>> %x=icmp.eq
>> >>>> %y=select %x,%r, null
>> >>>> %z=icmp.eq|neq %y, null
>> >>>> br %z,true, false
>> >>>> ==> %x=icmp.ne
>> >>>> %y=icmp.eq %r,null
>> >>>> %z=or %x,%y
>> >>>> br %z,true,false
>> >>>> The optimization is integrated into the instruction
>> >>>> combiner and performed only when all uses of the select result can
>> >>>> be replaced by the select operand proper. For this dominator
>> >>>> information
>> >>>> is used and dominance is now a required analysis pass in the
>> >>>> combiner.
>> >>>> The optimization itself is iterative. The critical step is to replace
>> >>>> the
>> >>>> select result with the non-constant select operand. So the select
>> >>>> becomes
>> >>>> local and the combiner iteratively works out simpler code pattern and
>> >>>> eventually eliminates the select.
>> >>>>
>> >>>> rdar://17853760
>> >>>>
>> >>>>
>> >>>> Added:
>> >>>> llvm/trunk/test/Transforms/InstCombine/select-cmp-br.ll
>> >>>> Modified:
>> >>>> llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
>> >>>> llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> >>>> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> >>>> llvm/trunk/test/Transforms/InstCombine/pr12338.ll
>> >>>>
>> >>>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
>> >>>> URL:
>> >>>>
>> >>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=218721&r1=218720&r2=218721&view=diff
>> >>>>
>> >>>>
>> >>>> ==============================================================================
>> >>>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)
>> >>>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Tue Sep 30
>> >>>> 19:13:22 2014
>> >>>> @@ -14,6 +14,7 @@
>> >>>> #include "llvm/Analysis/AssumptionTracker.h"
>> >>>> #include "llvm/Analysis/TargetFolder.h"
>> >>>> #include "llvm/Analysis/ValueTracking.h"
>> >>>> +#include "llvm/IR/Dominators.h"
>> >>>> #include "llvm/IR/IRBuilder.h"
>> >>>> #include "llvm/IR/InstVisitor.h"
>> >>>> #include "llvm/IR/IntrinsicInst.h"
>> >>>> @@ -98,7 +99,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombin
>> >>>> AssumptionTracker *AT;
>> >>>> const DataLayout *DL;
>> >>>> TargetLibraryInfo *TLI;
>> >>>> - DominatorTree *DT; // not required
>> >>>> + DominatorTree *DT;
>> >>>> bool MadeIRChange;
>> >>>> LibCallSimplifier *Simplifier;
>> >>>> bool MinimizeSize;
>> >>>> @@ -113,7 +114,8 @@ public:
>> >>>> BuilderTy *Builder;
>> >>>>
>> >>>> static char ID; // Pass identification, replacement for typeid
>> >>>> - InstCombiner() : FunctionPass(ID), DL(nullptr), Builder(nullptr) {
>> >>>> + InstCombiner()
>> >>>> + : FunctionPass(ID), DL(nullptr), DT(nullptr), Builder(nullptr)
>> >>>> {
>> >>>> MinimizeSize = false;
>> >>>> initializeInstCombinerPass(*PassRegistry::getPassRegistry());
>> >>>> }
>> >>>> @@ -242,6 +244,11 @@ public:
>> >>>>
>> >>>> // visitInstruction - Specify what to return for unhandled
>> >>>> instructions...
>> >>>> Instruction *visitInstruction(Instruction &I) { return nullptr; }
>> >>>> + bool dominatesAllUses(const Instruction *DI, const Instruction
>> >>>> *UI,
>> >>>> + const BasicBlock *DB) const;
>> >>>> + bool replacedSelectWithOperand(SelectInst *SI, const ICmpInst
>> >>>> *Icmp,
>> >>>> + const ConstantInt *CI1,
>> >>>> + const ConstantInt *CI2);
>> >>>>
>> >>>> private:
>> >>>> bool ShouldChangeType(Type *From, Type *To) const;
>> >>>>
>> >>>> Modified:
>> >>>> llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> >>>> URL:
>> >>>>
>> >>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=218721&r1=218720&r2=218721&view=diff
>> >>>>
>> >>>>
>> >>>> ==============================================================================
>> >>>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> >>>> (original)
>> >>>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Tue
>> >>>> Sep 30 19:13:22 2014
>> >>>> @@ -2429,6 +2429,127 @@ static bool swapMayExposeCSEOpportunitie
>> >>>> return GlobalSwapBenefits > 0;
>> >>>> }
>> >>>>
>> >>>> +/// \brief Check that one use is in the same block as the definition
>> >>>> and all
>> >>>> +/// other uses are in blocks dominated by a given block
>> >>>> +///
>> >>>> +/// \param DI Definition
>> >>>> +/// \param UI Use
>> >>>> +/// \param DB Block that must dominate all uses of \p DI outside
>> >>>> +/// the parent block. Note there can be a use of \p DI in
>> >>>> \p
>> >>>> DB.
>> >>>> +/// \return true when \p UI is the only use of \p DI in the parent
>> >>>> block
>> >>>> +/// and all other uses of \p DI are in blocks dominated by \p DB.
>> >>>> +///
>> >>>> +bool InstCombiner::dominatesAllUses(const Instruction *DI,
>> >>>> + const Instruction *UI,
>> >>>> + const BasicBlock *DB) const {
>> >>>> + assert(DI && DI->getParent() == UI->getParent() &&
>> >>>> + "definition and use must be in the same block");
>> >>>> + // DominatorTree available?
>> >>>> + if (!DT)
>> >>>> + return false;
>> >>>> + for (const User *U : DI->users()) {
>> >>>> + auto *Usr = cast<Instruction>(U);
>> >>>> + if (Usr != UI && !DT->dominates(DB, Usr->getParent()))
>> >>>> + return false;
>> >>>> + }
>> >>>> + return true;
>> >>>> +}
>> >>>> +
>> >>>> +///
>> >>>> +/// true when the instruction sequence within a block is
>> >>>> select-cmp-br.
>> >>>> +///
>> >>>> +static bool isChainSelectCmpBranch(const SelectInst *SI) {
>> >>>> + const BasicBlock *BB = SI->getParent();
>> >>>> + if (!BB)
>> >>>> + return false;
>> >>>> + auto *BI = dyn_cast_or_null<BranchInst>(BB->getTerminator());
>> >>>> + if (!BI || BI->getNumSuccessors() != 2)
>> >>>> + return false;
>> >>>> + auto *IC = dyn_cast<ICmpInst>(BI->getCondition());
>> >>>> + if (!IC || (IC->getOperand(0) != SI && IC->getOperand(1) != SI))
>> >>>> + return false;
>> >>>> + return true;
>> >>>> +}
>> >>>> +
>> >>>> +///
>> >>>> +/// \brief True when a select result is replaced by one of its
>> >>>> operands
>> >>>> +/// in select-icmp sequence. This will eventually result in the
>> >>>> elimination
>> >>>> +/// of the select.
>> >>>> +///
>> >>>> +/// \param SI Select instruction
>> >>>> +/// \param Icmp Compare instruction
>> >>>> +/// \param CI1 'true' when first select operand is equal to RHSC of
>> >>>> Icmp
>> >>>> +/// \param CI2 'true' when second select operand is equal to RHSC
>> >>>> of
>> >>>> Icmp
>> >>>> +///
>> >>>> +/// Notes:
>> >>>> +/// - The replacement is global and requires dominator information
>> >>>> +/// - The caller is responsible for the actual replacement
>> >>>> +///
>> >>>> +/// Example:
>> >>>> +///
>> >>>> +/// entry:
>> >>>> +/// %4 = select i1 %3, %C* %0, %C* null
>> >>>> +/// %5 = icmp eq %C* %4, null
>> >>>> +/// br i1 %5, label %9, label %7
>> >>>> +/// ...
>> >>>> +/// ; <label>:7 ; preds =
>> >>>> %entry
>> >>>> +/// %8 = getelementptr inbounds %C* %4, i64 0, i32 0
>> >>>> +/// ...
>> >>>> +///
>> >>>> +/// can be transformed to
>> >>>> +///
>> >>>> +/// %5 = icmp eq %C* %0, null
>> >>>> +/// %6 = select i1 %3, i1 %5, i1 true
>> >>>> +/// br i1 %6, label %9, label %7
>> >>>> +/// ...
>> >>>> +/// ; <label>:7 ; preds =
>> >>>> %entry
>> >>>> +/// %8 = getelementptr inbounds %C* %0, i64 0, i32 0 // replace by
>> >>>> %0!
>> >>>> +///
>> >>>> +/// Similar when the first operand of the select is a constant
>> >>>> or/and
>> >>>> +/// the compare is for not equal rather than equal.
>> >>>> +///
>> >>>> +/// FIXME: Currently the function considers equal compares only. It
>> >>>> should be
>> >>>> +/// possbile to extend it to not equal compares also.
>> >>>> +///
>> >>>> +bool InstCombiner::replacedSelectWithOperand(SelectInst *SI,
>> >>>> + const ICmpInst *Icmp,
>> >>>> + const ConstantInt *CI1,
>> >>>> + const ConstantInt *CI2)
>> >>>> {
>> >>>> + if (isChainSelectCmpBranch(SI) && Icmp->isEquality()) {
>> >>>> + // Code sequence is select - icmp.[eq|ne] - br
>> >>>> + unsigned ReplaceWithOpd = 0;
>> >>>> + if (CI1 && !CI1->isZero())
>> >>>> + // The first constant operand of the select and the RHS of
>> >>>> + // the compare match, so try to substitute
>> >>>> + // the select results with its second operand
>> >>>> + // Example:
>> >>>> + // %4 = select i1 %3, %C* null, %C* %0
>> >>>> + // %5 = icmp eq %C* %4, null
>> >>>> + // ==> could replace select with second operand
>> >>>> + ReplaceWithOpd = 2;
>> >>>> + else if (CI2 && !CI2->isZero())
>> >>>> + // Similar when the second operand of the select is a constant
>> >>>> + // Example:
>> >>>> + // %4 = select i1 %3, %C* %0, %C* null
>> >>>> + // %5 = icmp eq %C* %4, null
>> >>>> + // ==> could replace select with first operand
>> >>>> + ReplaceWithOpd = 1;
>> >>>> + if (ReplaceWithOpd) {
>> >>>> + // Replace select with operand on else path for EQ compares.
>> >>>> + // Replace select with operand on then path for NE compares.
>> >>>> + BasicBlock *Succ =
>> >>>> + Icmp->getPredicate() == ICmpInst::ICMP_EQ
>> >>>> + ? SI->getParent()->getTerminator()->getSuccessor(1)
>> >>>> + : SI->getParent()->getTerminator()->getSuccessor(0);
>> >>>> + if (InstCombiner::dominatesAllUses(SI, Icmp, Succ)) {
>> >>>> + SI->replaceAllUsesWith(SI->getOperand(ReplaceWithOpd));
>> >>>> + return true;
>> >>>> + }
>> >>>> + }
>> >>>> + }
>> >>>> + return false;
>> >>>> +}
>> >>>> +
>> >>>> Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
>> >>>> bool Changed = false;
>> >>>> Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
>> >>>> @@ -2885,8 +3006,21 @@ Instruction *InstCombiner::visitICmpInst
>> >>>> // fold to a constant (in which case the icmp is replaced
>> >>>> with
>> >>>> a select
>> >>>> // which will usually simplify) or this is the only user of
>> >>>> the
>> >>>> // select (in which case we are trading a select+icmp for a
>> >>>> simpler
>> >>>> - // select+icmp).
>> >>>> - if ((Op1 && Op2) || (LHSI->hasOneUse() && (Op1 || Op2))) {
>> >>>> + // select+icmp) or all uses of the select can be replaced
>> >>>> based
>> >>>> on
>> >>>> + // dominance information ("Global cases").
>> >>>> + bool Transform = false;
>> >>>> + if (Op1 && Op2)
>> >>>> + Transform = true;
>> >>>> + else if (Op1 || Op2) {
>> >>>> + if (LHSI->hasOneUse())
>> >>>> + Transform = true;
>> >>>> + else
>> >>>> + // Global cases
>> >>>> + Transform = replacedSelectWithOperand(
>> >>>> + cast<SelectInst>(LHSI), &I,
>> >>>> dyn_cast_or_null<ConstantInt>(Op1),
>> >>>> + dyn_cast_or_null<ConstantInt>(Op2));
>> >>>> + }
>> >>>> + if (Transform) {
>> >>>> if (!Op1)
>> >>>> Op1 = Builder->CreateICmp(I.getPredicate(),
>> >>>> LHSI->getOperand(1),
>> >>>> RHSC, I.getName());
>> >>>>
>> >>>> Modified:
>> >>>> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> >>>> URL:
>> >>>>
>> >>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=218721&r1=218720&r2=218721&view=diff
>> >>>>
>> >>>>
>> >>>> ==============================================================================
>> >>>> --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> >>>> (original)
>> >>>> +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> >>>> Tue
>> >>>> Sep 30 19:13:22 2014
>> >>>> @@ -90,6 +90,7 @@ INITIALIZE_PASS_BEGIN(InstCombiner, "ins
>> >>>> "Combine redundant instructions", false, false)
>> >>>> INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
>> >>>> INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
>> >>>> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
>> >>>> INITIALIZE_PASS_END(InstCombiner, "instcombine",
>> >>>> "Combine redundant instructions", false, false)
>> >>>>
>> >>>> @@ -97,6 +98,8 @@ void InstCombiner::getAnalysisUsage(Anal
>> >>>> AU.setPreservesCFG();
>> >>>> AU.addRequired<AssumptionTracker>();
>> >>>> AU.addRequired<TargetLibraryInfo>();
>> >>>> + AU.addRequired<DominatorTreeWrapperPass>();
>> >>>> + AU.addPreserved<DominatorTreeWrapperPass>();
>> >>>> }
>> >>>>
>> >>>>
>> >>>> @@ -2933,12 +2936,9 @@ bool InstCombiner::runOnFunction(Functio
>> >>>> AT = &getAnalysis<AssumptionTracker>();
>> >>>> DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
>> >>>> DL = DLP ? &DLP->getDataLayout() : nullptr;
>> >>>> + DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>> >>>> TLI = &getAnalysis<TargetLibraryInfo>();
>> >>>>
>> >>>> - DominatorTreeWrapperPass *DTWP =
>> >>>> - getAnalysisIfAvailable<DominatorTreeWrapperPass>();
>> >>>> - DT = DTWP ? &DTWP->getDomTree() : nullptr;
>> >>>> -
>> >>>> // Minimizing size?
>> >>>> MinimizeSize =
>> >>>> F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
>> >>>> Attribute::MinSize);
>> >>>>
>> >>>> Modified: llvm/trunk/test/Transforms/InstCombine/pr12338.ll
>> >>>> URL:
>> >>>>
>> >>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pr12338.ll?rev=218721&r1=218720&r2=218721&view=diff
>> >>>>
>> >>>>
>> >>>> ==============================================================================
>> >>>> --- llvm/trunk/test/Transforms/InstCombine/pr12338.ll (original)
>> >>>> +++ llvm/trunk/test/Transforms/InstCombine/pr12338.ll Tue Sep 30
>> >>>> 19:13:22 2014
>> >>>> @@ -2,11 +2,11 @@
>> >>>>
>> >>>> define void @entry() nounwind {
>> >>>> entry:
>> >>>> +; CHECK: br label %for.cond
>> >>>> br label %for.cond
>> >>>>
>> >>>> for.cond:
>> >>>> %local = phi <1 x i32> [ <i32 0>, %entry ], [ %phi2, %cond.end47 ]
>> >>>> -; CHECK: sub <1 x i32> <i32 92>, %local
>> >>>> %phi3 = sub <1 x i32> zeroinitializer, %local
>> >>>> br label %cond.end
>> >>>>
>> >>>>
>> >>>> Added: llvm/trunk/test/Transforms/InstCombine/select-cmp-br.ll
>> >>>> URL:
>> >>>>
>> >>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/select-cmp-br.ll?rev=218721&view=auto
>> >>>>
>> >>>>
>> >>>> ==============================================================================
>> >>>> --- llvm/trunk/test/Transforms/InstCombine/select-cmp-br.ll (added)
>> >>>> +++ llvm/trunk/test/Transforms/InstCombine/select-cmp-br.ll Tue Sep
>> >>>> 30
>> >>>> 19:13:22 2014
>> >>>> @@ -0,0 +1,127 @@
>> >>>> +; Replace a 'select' with 'or' in 'select - cmp [eq|ne] - br'
>> >>>> sequence
>> >>>> +; RUN: opt -instcombine -S < %s | FileCheck %s
>> >>>> +
>> >>>> +%C = type <{ %struct.S }>
>> >>>> +%struct.S = type { i64*, i32, i32 }
>> >>>> +
>> >>>> +declare void @bar(%struct.S *) #1
>> >>>> +
>> >>>> +define void @test1(%C*) {
>> >>>> +entry:
>> >>>> + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
>> >>>> + %m = load i64** %1, align 8
>> >>>> + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
>> >>>> + %n = load i64** %2, align 8
>> >>>> + %3 = getelementptr inbounds i64* %m, i64 9
>> >>>> + %4 = bitcast i64* %3 to i64 (%C*)**
>> >>>> + %5 = load i64 (%C*)** %4, align 8
>> >>>> + %6 = icmp eq i64* %m, %n
>> >>>> + %7 = select i1 %6, %C* %0, %C* null
>> >>>> + %8 = icmp eq %C* %7, null
>> >>>> + br i1 %8, label %12, label %10
>> >>>> +
>> >>>> +; <label>:9 ; preds = %10, %12
>> >>>> + ret void
>> >>>> +
>> >>>> +; <label>:10 ; preds = %entry
>> >>>> + %11 = getelementptr inbounds %C* %7, i64 0, i32 0
>> >>>> + tail call void @bar(%struct.S* %11)
>> >>>> + br label %9
>> >>>> +
>> >>>> +; <label>:12 ; preds = %entry
>> >>>> + %13 = tail call i64 %5(%C* %0)
>> >>>> + br label %9
>> >>>> +; CHECK-LABEL: @test1(
>> >>>> +; CHECK-NOT: select
>> >>>> +; CHECK: or
>> >>>> +}
>> >>>> +
>> >>>> +define void @test2(%C*) {
>> >>>> +entry:
>> >>>> + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
>> >>>> + %m = load i64** %1, align 8
>> >>>> + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
>> >>>> + %n = load i64** %2, align 8
>> >>>> + %3 = getelementptr inbounds i64* %m, i64 9
>> >>>> + %4 = bitcast i64* %3 to i64 (%C*)**
>> >>>> + %5 = load i64 (%C*)** %4, align 8
>> >>>> + %6 = icmp eq i64* %m, %n
>> >>>> + %7 = select i1 %6, %C* null, %C* %0
>> >>>> + %8 = icmp eq %C* %7, null
>> >>>> + br i1 %8, label %12, label %10
>> >>>> +
>> >>>> +; <label>:9 ; preds = %10, %12
>> >>>> + ret void
>> >>>> +
>> >>>> +; <label>:10 ; preds = %entry
>> >>>> + %11 = getelementptr inbounds %C* %7, i64 0, i32 0
>> >>>> + tail call void @bar(%struct.S* %11)
>> >>>> + br label %9
>> >>>> +
>> >>>> +; <label>:12 ; preds = %entry
>> >>>> + %13 = tail call i64 %5(%C* %0)
>> >>>> + br label %9
>> >>>> +; CHECK-LABEL: @test2(
>> >>>> +; CHECK-NOT: select
>> >>>> +; CHECK: or
>> >>>> +}
>> >>>> +
>> >>>> +define void @test3(%C*) {
>> >>>> +entry:
>> >>>> + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
>> >>>> + %m = load i64** %1, align 8
>> >>>> + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
>> >>>> + %n = load i64** %2, align 8
>> >>>> + %3 = getelementptr inbounds i64* %m, i64 9
>> >>>> + %4 = bitcast i64* %3 to i64 (%C*)**
>> >>>> + %5 = load i64 (%C*)** %4, align 8
>> >>>> + %6 = icmp eq i64* %m, %n
>> >>>> + %7 = select i1 %6, %C* %0, %C* null
>> >>>> + %8 = icmp ne %C* %7, null
>> >>>> + br i1 %8, label %10, label %12
>> >>>> +
>> >>>> +; <label>:9 ; preds = %10, %12
>> >>>> + ret void
>> >>>> +
>> >>>> +; <label>:10 ; preds = %entry
>> >>>> + %11 = getelementptr inbounds %C* %7, i64 0, i32 0
>> >>>> + tail call void @bar(%struct.S* %11)
>> >>>> + br label %9
>> >>>> +
>> >>>> +; <label>:12 ; preds = %entry
>> >>>> + %13 = tail call i64 %5(%C* %0)
>> >>>> + br label %9
>> >>>> +; CHECK-LABEL: @test3(
>> >>>> +; CHECK-NOT: select
>> >>>> +; CHECK: or
>> >>>> +}
>> >>>> +
>> >>>> +define void @test4(%C*) {
>> >>>> +entry:
>> >>>> + %1 = getelementptr inbounds %C* %0, i64 0, i32 0, i32 0
>> >>>> + %m = load i64** %1, align 8
>> >>>> + %2 = getelementptr inbounds %C* %0, i64 1, i32 0, i32 0
>> >>>> + %n = load i64** %2, align 8
>> >>>> + %3 = getelementptr inbounds i64* %m, i64 9
>> >>>> + %4 = bitcast i64* %3 to i64 (%C*)**
>> >>>> + %5 = load i64 (%C*)** %4, align 8
>> >>>> + %6 = icmp eq i64* %m, %n
>> >>>> + %7 = select i1 %6, %C* null, %C* %0
>> >>>> + %8 = icmp ne %C* %7, null
>> >>>> + br i1 %8, label %10, label %12
>> >>>> +
>> >>>> +; <label>:9 ; preds = %10, %12
>> >>>> + ret void
>> >>>> +
>> >>>> +; <label>:10 ; preds = %entry
>> >>>> + %11 = getelementptr inbounds %C* %7, i64 0, i32 0
>> >>>> + tail call void @bar(%struct.S* %11)
>> >>>> + br label %9
>> >>>> +
>> >>>> +; <label>:12 ; preds = %entry
>> >>>> + %13 = tail call i64 %5(%C* %0)
>> >>>> + br label %9
>> >>>> +; CHECK-LABEL: @test4(
>> >>>> +; CHECK-NOT: select
>> >>>> +; CHECK: or
>> >>>> +}
>> >>>>
>> >>>>
>> >>>> _______________________________________________
>> >>>> llvm-commits mailing list
>> >>>> llvm-commits at cs.uiuc.edu
>> >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> >>>
>> >>>
>> >>>
>> >>
>> >>
>> >
>> > _______________________________________________
>> > llvm-commits mailing list
>> > llvm-commits at cs.uiuc.edu
>> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> >
>
>
More information about the llvm-commits
mailing list