From 32d15d90c41c79b0f343c928b1a2d4aa2d4142ef Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Thu, 4 Jul 2013 14:22:02 +0000 Subject: [PATCH] SimplifyCFG: Teach switch generation some patterns that instcombine forms. This allows us to create switches even if instcombine has munged two of the incombing compares into one and some bit twiddling. This was motivated by enum compares that are common in clang. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185632 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 28 ++++++++++++++- test/Transforms/SimplifyCFG/switch_create.ll | 36 ++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 6d12f7a218d..d8878f2e512 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -40,12 +40,14 @@ #include "llvm/Support/ConstantRange.h" #include "llvm/Support/Debug.h" #include "llvm/Support/NoFolder.h" +#include "llvm/Support/PatternMatch.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include #include #include using namespace llvm; +using namespace PatternMatch; static cl::opt PHINodeFoldingThreshold("phi-node-folding-threshold", cl::Hidden, cl::init(1), @@ -432,7 +434,24 @@ GatherConstantCompares(Value *V, std::vector &Vals, Value *&Extra, // If this is an icmp against a constant, handle this as one of the cases. if (ICmpInst *ICI = dyn_cast(I)) { if (ConstantInt *C = GetConstantInt(I->getOperand(1), TD)) { + Value *RHSVal; + ConstantInt *RHSC; + if (ICI->getPredicate() == (isEQ ? ICmpInst::ICMP_EQ:ICmpInst::ICMP_NE)) { + // (x & ~2^x) == y --> x == y || x == y|2^x + // This undoes a transformation done by instcombine to fuse 2 compares. + if (match(ICI->getOperand(0), + m_And(m_Value(RHSVal), m_ConstantInt(RHSC)))) { + APInt Not = ~RHSC->getValue(); + if (Not.isPowerOf2()) { + Vals.push_back(C); + Vals.push_back( + ConstantInt::get(C->getContext(), C->getValue() | Not)); + UsedICmps++; + return RHSVal; + } + } + UsedICmps++; Vals.push_back(C); return I->getOperand(0); @@ -443,6 +462,13 @@ GatherConstantCompares(Value *V, std::vector &Vals, Value *&Extra, ConstantRange Span = ConstantRange::makeICmpRegion(ICI->getPredicate(), C->getValue()); + // Shift the range if the compare is fed by an add. This is the range + // compare idiom as emitted by instcombine. + bool hasAdd = + match(I->getOperand(0), m_Add(m_Value(RHSVal), m_ConstantInt(RHSC))); + if (hasAdd) + Span = Span.subtract(RHSC->getValue()); + // If this is an and/!= check then we want to optimize "x ugt 2" into // x != 0 && x != 1. if (!isEQ) @@ -455,7 +481,7 @@ GatherConstantCompares(Value *V, std::vector &Vals, Value *&Extra, for (APInt Tmp = Span.getLower(); Tmp != Span.getUpper(); ++Tmp) Vals.push_back(ConstantInt::get(V->getContext(), Tmp)); UsedICmps++; - return I->getOperand(0); + return hasAdd ? RHSVal : I->getOperand(0); } return 0; } diff --git a/test/Transforms/SimplifyCFG/switch_create.ll b/test/Transforms/SimplifyCFG/switch_create.ll index 546cc75f297..9d4e31961f4 100644 --- a/test/Transforms/SimplifyCFG/switch_create.ll +++ b/test/Transforms/SimplifyCFG/switch_create.ll @@ -479,3 +479,39 @@ return: ; CHECK: ret void } +define void @test18(i32 %arg) { +bb: + %tmp = and i32 %arg, -2 + %tmp1 = icmp eq i32 %tmp, 8 + %tmp2 = icmp eq i32 %arg, 10 + %tmp3 = or i1 %tmp1, %tmp2 + %tmp4 = icmp eq i32 %arg, 11 + %tmp5 = or i1 %tmp3, %tmp4 + %tmp6 = icmp eq i32 %arg, 12 + %tmp7 = or i1 %tmp5, %tmp6 + br i1 %tmp7, label %bb19, label %bb8 + +bb8: ; preds = %bb + %tmp9 = add i32 %arg, -13 + %tmp10 = icmp ult i32 %tmp9, 2 + %tmp11 = icmp eq i32 %arg, 16 + %tmp12 = or i1 %tmp10, %tmp11 + %tmp13 = icmp eq i32 %arg, 17 + %tmp14 = or i1 %tmp12, %tmp13 + %tmp15 = icmp eq i32 %arg, 18 + %tmp16 = or i1 %tmp14, %tmp15 + %tmp17 = icmp eq i32 %arg, 15 + %tmp18 = or i1 %tmp16, %tmp17 + br i1 %tmp18, label %bb19, label %bb20 + +bb19: ; preds = %bb8, %bb + tail call void @foo1() + br label %bb20 + +bb20: ; preds = %bb19, %bb8 + ret void + +; CHECK: @test18 +; CHECK: %arg.off = add i32 %arg, -8 +; CHECK: icmp ult i32 %arg.off, 11 +} -- 2.34.1