From e39b15195a3607ee708be9d105b5fc591b4665dd Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Tue, 17 Dec 2013 01:28:35 +0000 Subject: Merging r197449: ------------------------------------------------------------------------ r197449 | arnolds | 2013-12-16 17:11:01 -0800 (Mon, 16 Dec 2013) | 7 lines LoopVectorizer: Don't if-convert constant expressions that can trap A phi node operand or an instruction operand could be a constant expression that can trap (division). Check that we don't vectorize such cases. PR16729 radar://15653590 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_34@197453 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Vectorize/LoopVectorize.cpp | 32 ++++++++++++- test/Transforms/LoopVectorize/if-conversion.ll | 63 ++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 874db9ff15..5e758713ed 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -2781,6 +2781,23 @@ void InnerLoopVectorizer::updateAnalysis() { DEBUG(DT->verifyAnalysis()); } +/// \brief Check whether it is safe to if-convert this phi node. +/// +/// Phi nodes with constant expressions that can trap are not safe to if +/// convert. +static bool canIfConvertPHINodes(BasicBlock *BB) { + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + PHINode *Phi = dyn_cast(I); + if (!Phi) + return true; + for (unsigned p = 0, e = Phi->getNumIncomingValues(); p != e; ++p) + if (Constant *C = dyn_cast(Phi->getIncomingValue(p))) + if (C->canTrap()) + return false; + } + return true; +} + bool LoopVectorizationLegality::canVectorizeWithIfConvert() { if (!EnableIfConversion) return false; @@ -2807,6 +2824,7 @@ bool LoopVectorizationLegality::canVectorizeWithIfConvert() { } // Collect the blocks that need predication. + BasicBlock *Header = TheLoop->getHeader(); for (Loop::block_iterator BI = TheLoop->block_begin(), BE = TheLoop->block_end(); BI != BE; ++BI) { BasicBlock *BB = *BI; @@ -2816,8 +2834,12 @@ bool LoopVectorizationLegality::canVectorizeWithIfConvert() { return false; // We must be able to predicate all blocks that need to be predicated. - if (blockNeedsPredication(BB) && !blockCanBePredicated(BB, SafePointes)) + if (blockNeedsPredication(BB)) { + if (!blockCanBePredicated(BB, SafePointes)) + return false; + } else if (BB != Header && !canIfConvertPHINodes(BB)) return false; + } // We can if-convert this loop. @@ -4371,6 +4393,14 @@ bool LoopVectorizationLegality::blockCanBePredicated(BasicBlock *BB, if (it->mayWriteToMemory() || it->mayThrow()) return false; + // Check that we don't have a constant expression that can trap as operand. + for (Instruction::op_iterator OI = it->op_begin(), OE = it->op_end(); + OI != OE; ++OI) { + if (Constant *C = dyn_cast(*OI)) + if (C->canTrap()) + return false; + } + // The instructions below can trap. switch (it->getOpcode()) { default: continue; diff --git a/test/Transforms/LoopVectorize/if-conversion.ll b/test/Transforms/LoopVectorize/if-conversion.ll index 88e56b2457..dbe0243a81 100644 --- a/test/Transforms/LoopVectorize/if-conversion.ll +++ b/test/Transforms/LoopVectorize/if-conversion.ll @@ -106,3 +106,66 @@ for.end: ; preds = %for.inc, %entry ret i32 %sum.0.lcssa } +@a = common global [1 x i32*] zeroinitializer, align 8 +@c = common global i32* null, align 8 + +; We use to if convert this loop. This is not safe because there is a trapping +; constant expression. +; PR16729 + +; CHECK-LABEL: trapping_constant_expression +; CHECK-NOT: or <4 x i32> + +define i32 @trapping_constant_expression() { +entry: + br label %for.body + +for.body: + %inc3 = phi i32 [ 0, %entry ], [ %inc, %cond.end ] + %or2 = phi i32 [ 0, %entry ], [ %or, %cond.end ] + br i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 0), i32** @c), label %cond.false, label %cond.end + +cond.false: + br label %cond.end + +cond.end: + %cond = phi i32 [ sdiv (i32 1, i32 zext (i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 0), i32** @c) to i32)), %cond.false ], [ 0, %for.body ] + %or = or i32 %or2, %cond + %inc = add nsw i32 %inc3, 1 + %cmp = icmp slt i32 %inc, 128 + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret i32 %or +} + +; Neither should we if-convert if there is an instruction operand that is a +; trapping constant expression. +; PR16729 + +; CHECK-LABEL: trapping_constant_expression2 +; CHECK-NOT: or <4 x i32> + +define i32 @trapping_constant_expression2() { +entry: + br label %for.body + +for.body: + %inc3 = phi i32 [ 0, %entry ], [ %inc, %cond.end ] + %or2 = phi i32 [ 0, %entry ], [ %or, %cond.end ] + br i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 0), i32** @c), label %cond.false, label %cond.end + +cond.false: + %cond.1 = or i32 %inc3, sdiv (i32 1, i32 zext (i1 icmp eq (i32** getelementptr inbounds ([1 x i32*]* @a, i64 0, i64 0), i32** @c) to i32)) + br label %cond.end + +cond.end: + %cond = phi i32 [ %cond.1, %cond.false ], [ %inc3, %for.body ] + %or = or i32 %or2, %cond + %inc = add nsw i32 %inc3, 1 + %cmp = icmp slt i32 %inc, 128 + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret i32 %or +} -- cgit v1.2.3