diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp index 41bc22f6a330cf..368c3811532c8f 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp @@ -638,11 +638,11 @@ # endif # endif -#ifndef __cpp_lib_is_scoped_enum -#error "__cpp_lib_is_scoped_enum should be defined in c++2b" -#endif -#if __cpp_lib_is_scoped_enum != 202011L -#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" +# ifndef __cpp_lib_is_scoped_enum +# error "__cpp_lib_is_scoped_enum should be defined in c++2b" +# endif +# if __cpp_lib_is_scoped_enum != 202011L +# error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" # endif # ifndef __cpp_lib_is_swappable diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp index 3ff920c3a4891e..887416c9dcbef6 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -3983,11 +3983,11 @@ # endif # endif -#ifndef __cpp_lib_is_scoped_enum -#error "__cpp_lib_is_scoped_enum should be defined in c++2b" -#endif -#if __cpp_lib_is_scoped_enum != 202011L -#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" +# ifndef __cpp_lib_is_scoped_enum +# error "__cpp_lib_is_scoped_enum should be defined in c++2b" +# endif +# if __cpp_lib_is_scoped_enum != 202011L +# error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" # endif # ifndef __cpp_lib_is_swappable diff --git a/llvm/include/llvm/Analysis/LoopInfoImpl.h b/llvm/include/llvm/Analysis/LoopInfoImpl.h index 0730225c342fe6..426b349c6b8a9f 100644 --- a/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -673,7 +673,8 @@ static void compareLoops(const LoopT *L, const LoopT *OtherL, "Mismatched basic blocks in the loops!"); const SmallPtrSetImpl &BlocksSet = L->getBlocksSet(); - const SmallPtrSetImpl &OtherBlocksSet = L->getBlocksSet(); + const SmallPtrSetImpl &OtherBlocksSet = + OtherL->getBlocksSet(); assert(BlocksSet.size() == OtherBlocksSet.size() && llvm::all_of(BlocksSet, [&OtherBlocksSet](const BlockT *BB) { diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake index f4be1795f99948..a6ad213ab4362f 100644 --- a/llvm/include/llvm/Config/llvm-config.h.cmake +++ b/llvm/include/llvm/Config/llvm-config.h.cmake @@ -16,7 +16,7 @@ /* Indicate that this is LLVM compiled from the amd-gfx branch. */ #define LLVM_HAVE_BRANCH_AMD_GFX -#define LLVM_MAIN_REVISION 377324 +#define LLVM_MAIN_REVISION 377330 /* Define if LLVM_ENABLE_DUMP is enabled */ #cmakedefine LLVM_ENABLE_DUMP diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 3cab06079a87da..c40e5c36cdc7c8 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2127,12 +2127,21 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, Instruction::Xor, Q, MaxRecurse)) return V; - // If the operation is with the result of a select instruction, check whether - // operating on either branch of the select always yields the same value. - if (isa(Op0) || isa(Op1)) + if (isa(Op0) || isa(Op1)) { + if (Op0->getType()->isIntOrIntVectorTy(1)) { + // A & (A && B) -> A && B + if (match(Op1, m_Select(m_Specific(Op0), m_Value(), m_Zero()))) + return Op1; + else if (match(Op0, m_Select(m_Specific(Op1), m_Value(), m_Zero()))) + return Op0; + } + // If the operation is with the result of a select instruction, check + // whether operating on either branch of the select always yields the same + // value. if (Value *V = ThreadBinOpOverSelect(Instruction::And, Op0, Op1, Q, MaxRecurse)) return V; + } // If the operation is with the result of a phi instruction, check whether // operating on all incoming values of the phi always yields the same value. @@ -2303,12 +2312,21 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, Instruction::And, Q, MaxRecurse)) return V; - // If the operation is with the result of a select instruction, check whether - // operating on either branch of the select always yields the same value. - if (isa(Op0) || isa(Op1)) + if (isa(Op0) || isa(Op1)) { + if (Op0->getType()->isIntOrIntVectorTy(1)) { + // A | (A || B) -> A || B + if (match(Op1, m_Select(m_Specific(Op0), m_One(), m_Value()))) + return Op1; + else if (match(Op0, m_Select(m_Specific(Op1), m_One(), m_Value()))) + return Op0; + } + // If the operation is with the result of a select instruction, check + // whether operating on either branch of the select always yields the same + // value. if (Value *V = ThreadBinOpOverSelect(Instruction::Or, Op0, Op1, Q, MaxRecurse)) return V; + } // (A & C1)|(B & C2) const APInt *C1, *C2; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 352126fa07ca24..c42f113feca371 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -3444,19 +3444,30 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) { } } - // Pull 'not' into operands of select if both operands are one-use compares. + // Pull 'not' into operands of select if both operands are one-use compares + // or one is one-use compare and the other one is a constant. // Inverting the predicates eliminates the 'not' operation. // Example: - // not (select ?, (cmp TPred, ?, ?), (cmp FPred, ?, ?) --> + // not (select ?, (cmp TPred, ?, ?), (cmp FPred, ?, ?) --> // select ?, (cmp InvTPred, ?, ?), (cmp InvFPred, ?, ?) - // TODO: Canonicalize by hoisting 'not' into an arm of the select if only - // 1 select operand is a cmp? + // not (select ?, (cmp TPred, ?, ?), true --> + // select ?, (cmp InvTPred, ?, ?), false if (auto *Sel = dyn_cast(Op0)) { - auto *CmpT = dyn_cast(Sel->getTrueValue()); - auto *CmpF = dyn_cast(Sel->getFalseValue()); - if (CmpT && CmpF && CmpT->hasOneUse() && CmpF->hasOneUse()) { - CmpT->setPredicate(CmpT->getInversePredicate()); - CmpF->setPredicate(CmpF->getInversePredicate()); + Value *TV = Sel->getTrueValue(); + Value *FV = Sel->getFalseValue(); + auto *CmpT = dyn_cast(TV); + auto *CmpF = dyn_cast(FV); + bool InvertibleT = (CmpT && CmpT->hasOneUse()) || isa(TV); + bool InvertibleF = (CmpF && CmpF->hasOneUse()) || isa(FV); + if (InvertibleT && InvertibleF) { + if (CmpT) + CmpT->setPredicate(CmpT->getInversePredicate()); + else + Sel->setTrueValue(ConstantExpr::getNot(cast(TV))); + if (CmpF) + CmpF->setPredicate(CmpF->getInversePredicate()); + else + Sel->setFalseValue(ConstantExpr::getNot(cast(FV))); return replaceInstUsesWith(I, Sel); } } diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 7fe33fd3c75998..a243a2e37950f7 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -692,7 +692,7 @@ struct ConstantComparesGatherer { /// vector. /// One "Extra" case is allowed to differ from the other. void gather(Value *V) { - bool isEQ = (cast(V)->getOpcode() == Instruction::Or); + bool isEQ = match(V, m_LogicalOr(m_Value(), m_Value())); // Keep a stack (SmallVector for efficiency) for depth-first traversal SmallVector DFT; @@ -707,11 +707,14 @@ struct ConstantComparesGatherer { if (Instruction *I = dyn_cast(V)) { // If it is a || (or && depending on isEQ), process the operands. - if (I->getOpcode() == (isEQ ? Instruction::Or : Instruction::And)) { - if (Visited.insert(I->getOperand(1)).second) - DFT.push_back(I->getOperand(1)); - if (Visited.insert(I->getOperand(0)).second) - DFT.push_back(I->getOperand(0)); + Value *Op0, *Op1; + if (isEQ ? match(I, m_LogicalOr(m_Value(Op0), m_Value(Op1))) + : match(I, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) { + if (Visited.insert(Op1).second) + DFT.push_back(Op1); + if (Visited.insert(Op0).second) + DFT.push_back(Op0); + continue; } @@ -4147,7 +4150,7 @@ bool SimplifyCFGOpt::SimplifyBranchOnICmpChain(BranchInst *BI, if (UsedICmps <= 1) return false; - bool TrueWhenEqual = (Cond->getOpcode() == Instruction::Or); + bool TrueWhenEqual = match(Cond, m_LogicalOr(m_Value(), m_Value())); // There might be duplicate constants in the list, which the switch // instruction can't handle, remove them now. diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll index 48235863d9ff7e..35f100302d47b2 100644 --- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll +++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll @@ -56,8 +56,7 @@ define i1 @cond_eq_or_const(i8 %X, i8 %Y) { define i1 @merge_and(i1 %X, i1 %Y) { ; CHECK-LABEL: @merge_and( ; CHECK-NEXT: [[C:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false -; CHECK-NEXT: [[RES:%.*]] = and i1 [[C]], [[X]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 [[C]] ; %c = select i1 %X, i1 %Y, i1 false %res = and i1 %X, %c @@ -67,8 +66,7 @@ define i1 @merge_and(i1 %X, i1 %Y) { define i1 @merge_or(i1 %X, i1 %Y) { ; CHECK-LABEL: @merge_or( ; CHECK-NEXT: [[C:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] -; CHECK-NEXT: [[RES:%.*]] = or i1 [[C]], [[X]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 [[C]] ; %c = select i1 %X, i1 true, i1 %Y %res = or i1 %X, %c @@ -77,10 +75,10 @@ define i1 @merge_or(i1 %X, i1 %Y) { define i1 @xor_and(i1 %c, i32 %X, i32 %Y) { ; CHECK-LABEL: @xor_and( -; CHECK-NEXT: [[COMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i1 [[COMP]], i1 false -; CHECK-NEXT: [[RES:%.*]] = xor i1 [[SEL]], true -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[COMP]] +; CHECK-NEXT: ret i1 [[SEL]] ; %comp = icmp ult i32 %X, %Y %sel = select i1 %c, i1 %comp, i1 false @@ -90,10 +88,9 @@ define i1 @xor_and(i1 %c, i32 %X, i32 %Y) { define <2 x i1> @xor_and2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_and2( -; CHECK-NEXT: [[COMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> -; CHECK-NEXT: [[RES:%.*]] = xor <2 x i1> [[SEL]], -; CHECK-NEXT: ret <2 x i1> [[RES]] +; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> +; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y %sel = select <2 x i1> %c, <2 x i1> %comp, <2 x i1> @@ -105,10 +102,9 @@ define <2 x i1> @xor_and2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define <2 x i1> @xor_and3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_and3( -; CHECK-NEXT: [[COMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> -; CHECK-NEXT: [[RES:%.*]] = xor <2 x i1> [[SEL]], -; CHECK-NEXT: ret <2 x i1> [[RES]] +; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> +; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y %sel = select <2 x i1> %c, <2 x i1> %comp, <2 x i1> @@ -118,10 +114,10 @@ define <2 x i1> @xor_and3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define i1 @xor_or(i1 %c, i32 %X, i32 %Y) { ; CHECK-LABEL: @xor_or( -; CHECK-NEXT: [[COMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[COMP]] -; CHECK-NEXT: [[RES:%.*]] = xor i1 [[SEL]], true -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 [[COMP]], i1 false +; CHECK-NEXT: ret i1 [[SEL]] ; %comp = icmp ult i32 %X, %Y %sel = select i1 %c, i1 true, i1 %comp @@ -131,10 +127,9 @@ define i1 @xor_or(i1 %c, i32 %X, i32 %Y) { define <2 x i1> @xor_or2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_or2( -; CHECK-NEXT: [[COMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] -; CHECK-NEXT: [[RES:%.*]] = xor <2 x i1> [[SEL]], -; CHECK-NEXT: ret <2 x i1> [[RES]] +; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] +; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y %sel = select <2 x i1> %c, <2 x i1> , <2 x i1> %comp @@ -144,10 +139,9 @@ define <2 x i1> @xor_or2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define <2 x i1> @xor_or3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_or3( -; CHECK-NEXT: [[COMP:%.*]] = icmp ult <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] -; CHECK-NEXT: [[RES:%.*]] = xor <2 x i1> [[SEL]], -; CHECK-NEXT: ret <2 x i1> [[RES]] +; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] +; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y %sel = select <2 x i1> %c, <2 x i1> , <2 x i1> %comp diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll index a4c84a66cafbf4..3a047313b44a82 100644 --- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll @@ -33,10 +33,10 @@ F: ; preds = %0 define void @test1_select(i32 %V) { ; CHECK-LABEL: @test1_select( -; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[V:%.*]], 4 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[V]], 17 -; CHECK-NEXT: [[CN:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]] -; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] +; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [ +; CHECK-NEXT: i32 17, label [[T:%.*]] +; CHECK-NEXT: i32 4, label [[T]] +; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -135,10 +135,10 @@ F: ; preds = %0 define void @test2_select(i32 %V) { ; CHECK-LABEL: @test2_select( -; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[V:%.*]], 4 -; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[V]], 17 -; CHECK-NEXT: [[CN:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false -; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]] +; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [ +; CHECK-NEXT: i32 17, label [[F:%.*]] +; CHECK-NEXT: i32 4, label [[F]] +; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void @@ -465,13 +465,17 @@ F: define i32 @test10_select(i32 %mode, i1 %Cond) { ; CHECK-LABEL: @test10_select( -; CHECK-NEXT: T: -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 -; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i1 [[COND:%.*]], i1 false -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] +; CHECK: switch.early.test: +; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ +; CHECK-NEXT: i32 51, label [[F]] +; CHECK-NEXT: i32 0, label [[F]] +; CHECK-NEXT: ] +; CHECK: T: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK: F: +; CHECK-NEXT: br label [[T]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -488,13 +492,17 @@ F: ; TODO: %Cond doesn't need freeze define i32 @test10_select_and(i32 %mode, i1 %Cond) { ; CHECK-LABEL: @test10_select_and( -; CHECK-NEXT: T: -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 -; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false -; CHECK-NEXT: [[D:%.*]] = and i1 [[C]], [[COND:%.*]] -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] +; CHECK: switch.early.test: +; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ +; CHECK-NEXT: i32 51, label [[F]] +; CHECK-NEXT: i32 0, label [[F]] +; CHECK-NEXT: ] +; CHECK: T: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK: F: +; CHECK-NEXT: br label [[T]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -510,13 +518,17 @@ F: define i32 @test10_select_nofreeze(i32 %mode, i1 noundef %Cond) { ; CHECK-LABEL: @test10_select_nofreeze( -; CHECK-NEXT: T: -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0 -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51 -; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i1 [[COND:%.*]], i1 false -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]] +; CHECK: switch.early.test: +; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [ +; CHECK-NEXT: i32 51, label [[F]] +; CHECK-NEXT: i32 0, label [[F]] +; CHECK-NEXT: ] +; CHECK: T: +; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK: F: +; CHECK-NEXT: br label [[T]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -903,11 +915,11 @@ else: define void @test19_select(i32 %arg) { ; CHECK-LABEL: @test19_select( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARG:%.*]], -2 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND]], 12 -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[ARG]], 32 -; CHECK-NEXT: [[PRED:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [ +; CHECK-NEXT: i32 32, label [[IF:%.*]] +; CHECK-NEXT: i32 13, label [[IF]] +; CHECK-NEXT: i32 12, label [[IF]] +; CHECK-NEXT: ] ; CHECK: if: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: ret void diff --git a/openmp/docs/SupportAndFAQ.rst b/openmp/docs/SupportAndFAQ.rst index ef209aed17a0ee..80106bc1f4f1d0 100644 --- a/openmp/docs/SupportAndFAQ.rst +++ b/openmp/docs/SupportAndFAQ.rst @@ -56,7 +56,7 @@ To build an *effective* OpenMP offload capable compiler, only one extra CMake option, `LLVM_ENABLE_RUNTIMES="openmp"`, is needed when building LLVM (Generic information about building LLVM is available `here `__.). Make sure all backends that are targeted by OpenMP to be enabled. By default, -Clang will be build with all backends enabled. +Clang will be built with all backends enabled. If your build machine is not the target machine or automatic detection of the available GPUs failed, you should also set: @@ -66,8 +66,8 @@ available GPUs failed, you should also set: .. note:: The compiler that generates the offload code should be the same (version) as - the compiler that build the OpenMP device runtimes. The OpenMP host runtime - can be build by a different compiler. + the compiler that builds the OpenMP device runtimes. The OpenMP host runtime + can be built by a different compiler. .. _advanced_builds: https://llvm.org//docs/AdvancedBuilds.html