diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index a1f759dd1df83..f3963f3f4fafb 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -520,37 +520,6 @@ static bool dominatesMergePoint( return true; } -/// Extract ConstantInt from value, looking through IntToPtr -/// and PointerNullValue. Return NULL if value is not a constant int. -static ConstantInt *getConstantInt(Value *V, const DataLayout &DL) { - // Normal constant int. - ConstantInt *CI = dyn_cast(V); - if (CI || !isa(V) || !V->getType()->isPointerTy() || - DL.isNonIntegralPointerType(V->getType())) - return CI; - - // This is some kind of pointer constant. Turn it into a pointer-sized - // ConstantInt if possible. - IntegerType *PtrTy = cast(DL.getIntPtrType(V->getType())); - - // Null pointer means 0, see SelectionDAGBuilder::getValue(const Value*). - if (isa(V)) - return ConstantInt::get(PtrTy, 0); - - // IntToPtr const int. - if (ConstantExpr *CE = dyn_cast(V)) - if (CE->getOpcode() == Instruction::IntToPtr) - if (ConstantInt *CI = dyn_cast(CE->getOperand(0))) { - // The constant is very likely to have the right type already. - if (CI->getType() == PtrTy) - return CI; - else - return cast( - ConstantFoldIntegerCast(CI, PtrTy, /*isSigned=*/false, DL)); - } - return nullptr; -} - namespace { /// Given a chain of or (||) or and (&&) comparison of a value against a @@ -641,7 +610,7 @@ struct ConstantComparesGatherer { ICmpInst *ICI; ConstantInt *C; if (!((ICI = dyn_cast(I)) && - (C = getConstantInt(I->getOperand(1), DL)))) { + match(I->getOperand(1), m_ConstantInt(C)))) { return false; } @@ -858,7 +827,7 @@ Value *SimplifyCFGOpt::isValueEqualityComparison(Instruction *TI) { } else if (BranchInst *BI = dyn_cast(TI)) if (BI->isConditional() && BI->getCondition()->hasOneUse()) { if (ICmpInst *ICI = dyn_cast(BI->getCondition())) { - if (ICI->isEquality() && getConstantInt(ICI->getOperand(1), DL)) + if (ICI->isEquality() && match(ICI->getOperand(1), m_ConstantInt())) CV = ICI->getOperand(0); } else if (auto *Trunc = dyn_cast(BI->getCondition())) { if (Trunc->hasNoUnsignedWrap()) @@ -895,7 +864,7 @@ BasicBlock *SimplifyCFGOpt::getValueEqualityComparisonCases( ConstantInt *C; if (auto *ICI = dyn_cast(Cond)) { Pred = ICI->getPredicate(); - C = getConstantInt(ICI->getOperand(1), DL); + match(ICI->getOperand(1), m_ConstantInt(C)); } else { Pred = ICmpInst::ICMP_NE; auto *Trunc = cast(Cond); diff --git a/llvm/test/Transforms/SimplifyCFG/X86/MagicPointer.ll b/llvm/test/Transforms/SimplifyCFG/X86/MagicPointer.ll index 413406f921be6..ddd277563fdde 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/MagicPointer.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/MagicPointer.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; Test that simplifycfg can create switch instructions from constant pointers. ; ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s @@ -19,14 +20,40 @@ declare i32 @puts(ptr) declare i32 @puts_as1(ptr addrspace(1)) define void @f(ptr %x) nounwind ssp { -; CHECK-LABEL: @f( -; CHECK: switch i64 %magicptr -; CHECK: i64 0, label -; CHECK: i64 1, label -; CHECK: i64 2, label -; CHECK: i64 3, label -; CHECK: i64 4, label -; CHECK: } +; CHECK-LABEL: define void @f( +; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[X]], null +; CHECK-NEXT: br i1 [[TOBOOL]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @puts(ptr @.str) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: br label %[[IF_END21:.*]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[X]], inttoptr (i64 1 to ptr) +; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN2:.*]], label %[[IF_ELSE4:.*]] +; CHECK: [[IF_THEN2]]: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @puts(ptr @.str1) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_ELSE4]]: +; CHECK-NEXT: [[CMP6:%.*]] = icmp eq ptr [[X]], inttoptr (i64 2 to ptr) +; CHECK-NEXT: [[CMP8:%.*]] = icmp eq ptr [[X]], inttoptr (i64 3 to ptr) +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP6]], [[CMP8]] +; CHECK-NEXT: br i1 [[OR_COND]], label %[[IF_THEN9:.*]], label %[[IF_ELSE11:.*]] +; CHECK: [[IF_THEN9]]: +; CHECK-NEXT: [[CALL10:%.*]] = call i32 @puts(ptr @.str2) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_ELSE11]]: +; CHECK-NEXT: [[CMP13:%.*]] = icmp eq ptr [[X]], inttoptr (i64 4 to ptr) +; CHECK-NEXT: br i1 [[CMP13]], label %[[IF_THEN14:.*]], label %[[IF_ELSE16:.*]] +; CHECK: [[IF_THEN14]]: +; CHECK-NEXT: [[CALL15:%.*]] = call i32 @puts(ptr @.str3) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_ELSE16]]: +; CHECK-NEXT: [[CALL18:%.*]] = call i32 @puts(ptr [[X]]) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_END21]]: +; CHECK-NEXT: ret void +; entry: %tobool = icmp eq ptr %x, null ; [#uses=1] @@ -84,15 +111,40 @@ if.end21: ; preds = %if.end20, %if.then ; Is it useful to test a version where the ptrtoints are to the same ; size? define void @f_as1(ptr addrspace(1) %x) nounwind ssp { -; CHECK-LABEL: @f_as1( -; CHECK: ptrtoint ptr addrspace(1) %x to i16 -; CHECK: switch i16 %magicptr -; CHECK: i16 0, label -; CHECK: i16 1, label -; CHECK: i16 2, label -; CHECK: i16 3, label -; CHECK: i16 4, label -; CHECK: } +; CHECK-LABEL: define void @f_as1( +; CHECK-SAME: ptr addrspace(1) [[X:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr addrspace(1) [[X]], null +; CHECK-NEXT: br i1 [[TOBOOL]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]] +; CHECK: [[IF_THEN]]: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str_as1) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21:.*]] +; CHECK: [[IF_ELSE]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 1 to ptr addrspace(1)) +; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN2:.*]], label %[[IF_ELSE4:.*]] +; CHECK: [[IF_THEN2]]: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str1_as1) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_ELSE4]]: +; CHECK-NEXT: [[CMP6:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 2 to ptr addrspace(1)) +; CHECK-NEXT: [[CMP8:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 3 to ptr addrspace(1)) +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[CMP6]], [[CMP8]] +; CHECK-NEXT: br i1 [[OR_COND]], label %[[IF_THEN9:.*]], label %[[IF_ELSE11:.*]] +; CHECK: [[IF_THEN9]]: +; CHECK-NEXT: [[CALL10:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str2_as1) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_ELSE11]]: +; CHECK-NEXT: [[CMP13:%.*]] = icmp eq ptr addrspace(1) [[X]], inttoptr (i64 4 to ptr addrspace(1)) +; CHECK-NEXT: br i1 [[CMP13]], label %[[IF_THEN14:.*]], label %[[IF_ELSE16:.*]] +; CHECK: [[IF_THEN14]]: +; CHECK-NEXT: [[CALL15:%.*]] = call i32 @puts_as1(ptr addrspace(1) @.str3_as1) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_ELSE16]]: +; CHECK-NEXT: [[CALL18:%.*]] = call i32 @puts_as1(ptr addrspace(1) [[X]]) #[[ATTR1]] +; CHECK-NEXT: br label %[[IF_END21]] +; CHECK: [[IF_END21]]: +; CHECK-NEXT: ret void +; entry: %tobool = icmp eq ptr addrspace(1) %x, null ; [#uses=1] diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll b/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll index 336fc5e14d758..9a72212dac60f 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll @@ -35,11 +35,10 @@ F: ; preds = %0 define void @test1_ptr(ptr %V) { ; CHECK-LABEL: @test1_ptr( -; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr [[V:%.*]] to i40 -; CHECK-NEXT: switch i40 [[MAGICPTR]], label [[F:%.*]] [ -; CHECK-NEXT: i40 17, label [[T:%.*]] -; CHECK-NEXT: i40 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr [[V:%.*]], inttoptr (i32 4 to ptr) +; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr [[V]], inttoptr (i32 17 to ptr) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: common.ret: ; CHECK-NEXT: ret void ; CHECK: T: @@ -63,11 +62,10 @@ F: ; preds = %0 define void @test1_ptr_as1(ptr addrspace(1) %V) { ; CHECK-LABEL: @test1_ptr_as1( -; CHECK-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr addrspace(1) [[V:%.*]] to i40 -; CHECK-NEXT: switch i40 [[MAGICPTR]], label [[F:%.*]] [ -; CHECK-NEXT: i40 17, label [[T:%.*]] -; CHECK-NEXT: i40 4, label [[T]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr addrspace(1) [[V:%.*]], inttoptr (i32 4 to ptr addrspace(1)) +; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr addrspace(1) [[V]], inttoptr (i32 17 to ptr addrspace(1)) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] ; CHECK: common.ret: ; CHECK-NEXT: ret void ; CHECK: T: diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll index 18c4ade46162c..9deb38992dee0 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll @@ -61,20 +61,19 @@ F: } define void @test1_ptr(ptr %V) { -; DL-LABEL: @test1_ptr( -; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr [[V:%.*]] to i32 -; DL-NEXT: switch i32 [[MAGICPTR]], label [[F:%.*]] [ -; DL-NEXT: i32 17, label [[T:%.*]] -; DL-NEXT: i32 4, label [[T]] -; DL-NEXT: ] -; DL: common.ret: -; DL-NEXT: ret void -; DL: T: -; DL-NEXT: call void @foo1() -; DL-NEXT: br label [[COMMON_RET:%.*]] -; DL: F: -; DL-NEXT: call void @foo2() -; DL-NEXT: br label [[COMMON_RET]] +; CHECK-LABEL: @test1_ptr( +; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr [[V:%.*]], inttoptr (i32 4 to ptr) +; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr [[V]], inttoptr (i32 17 to ptr) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: T: +; CHECK-NEXT: call void @foo1() +; CHECK-NEXT: br label [[COMMON_RET:%.*]] +; CHECK: F: +; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] ; %C1 = icmp eq ptr %V, inttoptr (i32 4 to ptr) %C2 = icmp eq ptr %V, inttoptr (i32 17 to ptr) @@ -89,20 +88,19 @@ F: ; preds = %0 } define void @test1_ptr_as1(ptr addrspace(1) %V) { -; DL-LABEL: @test1_ptr_as1( -; DL-NEXT: [[MAGICPTR:%.*]] = ptrtoint ptr addrspace(1) [[V:%.*]] to i16 -; DL-NEXT: switch i16 [[MAGICPTR]], label [[F:%.*]] [ -; DL-NEXT: i16 17, label [[T:%.*]] -; DL-NEXT: i16 4, label [[T]] -; DL-NEXT: ] -; DL: common.ret: -; DL-NEXT: ret void -; DL: T: -; DL-NEXT: call void @foo1() -; DL-NEXT: br label [[COMMON_RET:%.*]] -; DL: F: -; DL-NEXT: call void @foo2() -; DL-NEXT: br label [[COMMON_RET]] +; CHECK-LABEL: @test1_ptr_as1( +; CHECK-NEXT: [[C1:%.*]] = icmp eq ptr addrspace(1) [[V:%.*]], inttoptr (i32 4 to ptr addrspace(1)) +; CHECK-NEXT: [[C2:%.*]] = icmp eq ptr addrspace(1) [[V]], inttoptr (i32 17 to ptr addrspace(1)) +; CHECK-NEXT: [[CN:%.*]] = or i1 [[C1]], [[C2]] +; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] +; CHECK: common.ret: +; CHECK-NEXT: ret void +; CHECK: T: +; CHECK-NEXT: call void @foo1() +; CHECK-NEXT: br label [[COMMON_RET:%.*]] +; CHECK: F: +; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] ; %C1 = icmp eq ptr addrspace(1) %V, inttoptr (i32 4 to ptr addrspace(1)) %C2 = icmp eq ptr addrspace(1) %V, inttoptr (i32 17 to ptr addrspace(1)) @@ -1313,3 +1311,5 @@ if.then: if.end: ret void } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; DL: {{.*}}