From 4ee6f6446b4737ab4f92be30fed4db4029970b49 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 27 Jan 2016 02:43:28 +0000 Subject: [PATCH] [SimplifyCFG] Don't mistake icmp of and for a tree of comparisons SimplifyCFG tries to turn complex branch conditions into a switch. Some of it's logic attempts to reason about bitwise arithmetic produced by InstCombine. InstCombine can turn things like (X == 2) || (X == 3) into (X & 1) == 2 and so SimplifyCFG tries to detect when this occurs so that it can produce a switch instruction. However, the legality checking was not sufficient to determine whether or not this had occured. Correctly check this case by requiring that the right-hand side of the comparison be a power of two. This fixes PR26323. llvm-svn: 258904 --- lib/Transforms/Utils/SimplifyCFG.cpp | 5 ++-- test/Transforms/SimplifyCFG/switch_create.ll | 25 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index b6d87c22e43..57adcecbdfb 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -405,13 +405,14 @@ private: ConstantInt *RHSC; // Pattern match a special case - // (x & ~2^x) == y --> x == y || x == y|2^x + // (x & ~2^z) == y --> x == y || x == y|2^z // This undoes a transformation done by instcombine to fuse 2 compares. if (ICI->getPredicate() == (isEQ ? ICmpInst::ICMP_EQ:ICmpInst::ICMP_NE)) { if (match(ICI->getOperand(0), m_And(m_Value(RHSVal), m_ConstantInt(RHSC)))) { APInt Not = ~RHSC->getValue(); - if (Not.isPowerOf2()) { + if (Not.isPowerOf2() && C->getValue().isPowerOf2() && + Not != C->getValue()) { // If we already have a value for the switch, it has to match! if(!setValueOnce(RHSVal)) return false; diff --git a/test/Transforms/SimplifyCFG/switch_create.ll b/test/Transforms/SimplifyCFG/switch_create.ll index 490b7513a94..f895a9f0284 100644 --- a/test/Transforms/SimplifyCFG/switch_create.ll +++ b/test/Transforms/SimplifyCFG/switch_create.ll @@ -554,3 +554,28 @@ bb20: ; preds = %bb19, %bb8 ; CHECK: %arg.off = add i32 %arg, -8 ; CHECK: icmp ult i32 %arg.off, 11 } + +define void @PR26323(i1 %tobool23, i32 %tmp3) { +entry: + %tobool5 = icmp ne i32 %tmp3, 0 + %neg14 = and i32 %tmp3, -2 + %cmp17 = icmp ne i32 %neg14, -1 + %or.cond = and i1 %tobool5, %tobool23 + %or.cond1 = and i1 %cmp17, %or.cond + br i1 %or.cond1, label %if.end29, label %if.then27 + +if.then27: ; preds = %entry + call void @foo1() + unreachable + +if.end29: ; preds = %entry + ret void +} + +; CHECK-LABEL: define void @PR26323( +; CHECK: %tobool5 = icmp ne i32 %tmp3, 0 +; CHECK: %neg14 = and i32 %tmp3, -2 +; CHECK: %cmp17 = icmp ne i32 %neg14, -1 +; CHECK: %or.cond = and i1 %tobool5, %tobool23 +; CHECK: %or.cond1 = and i1 %cmp17, %or.cond +; CHECK: br i1 %or.cond1, label %if.end29, label %if.then27