Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -461,6 +461,9 @@ QUERY( (y & ~mask = y) => ((x & ~mask = y) <=> (x = y OR x = (y | mask))) ); + QUERY( (y | mask = y) => + ((x | mask = y) <=> (x = y OR x = (y & ~mask))) + ); */ // Please note that each pattern must be a dual implication (<--> or @@ -503,6 +506,28 @@ } } + // Pattern match a special case: + /* + QUERY( (y | mask = y) => + ((x | mask = y) <=> (x = y OR x = (y & ~mask))) + ); + */ + if (match(ICI->getOperand(0), + m_Or(m_Value(RHSVal), m_APInt(RHSC)))) { + APInt Mask = *RHSC; + if (Mask.isPowerOf2() && (C->getValue() | Mask) == C->getValue()) { + // If we already have a value for the switch, it has to match! + if (!setValueOnce(RHSVal)) + return false; + + Vals.push_back(C); + Vals.push_back(ConstantInt::get(C->getContext(), + C->getValue() & ~Mask)); + UsedICmps++; + return true; + } + } + // If we already have a value for the switch, it has to match! if (!setValueOnce(ICI->getOperand(0))) return false; Index: test/Transforms/SimplifyCFG/switch_create.ll =================================================================== --- test/Transforms/SimplifyCFG/switch_create.ll +++ test/Transforms/SimplifyCFG/switch_create.ll @@ -618,4 +618,43 @@ else: ret void +} + +; Form a switch when or'ing a power of two +; CHECK-LABEL: define void @test21 +; CHECK: i32 32, label %else +; CHECK: i32 13, label %else +; CHECK: i32 12, label %else +define void @test21(i32 %arg) { + %and = or i32 %arg, 1 + %cmp1 = icmp ne i32 %and, 13 + %cmp2 = icmp ne i32 %arg, 32 + %pred = and i1 %cmp1, %cmp2 + br i1 %pred, label %if, label %else + +if: + call void @foo1() + ret void + +else: + ret void +} + +; Since %cmp1 is always false, a switch is never formed +; CHECK-LABEL: define void @test22 +; CHECK-NOT: switch +; CHECK: ret void +define void @test22(i32 %arg) { + %and = or i32 %arg, 1 + %cmp1 = icmp ne i32 %and, 12 + %cmp2 = icmp ne i32 %arg, 32 + %pred = and i1 %cmp1, %cmp2 + br i1 %pred, label %if, label %else + +if: + call void @foo1() + ret void + +else: + ret void } \ No newline at end of file