diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -6131,7 +6131,8 @@ // Into: // start: // %cmp = cmp uge i32 %a, %b - // br i1 %cmp, label %select.true, label %select.false + // %cmp.fr = freeze %cmp + // br i1 %cmp.fr, label %select.true, label %select.false // select.true: // br label %select.end // select.false: @@ -6139,6 +6140,7 @@ // select.end: // %sel = phi i32 [ %c, %select.true ], [ %d, %select.false ] // + // %cmp should be freezed, otherwise it may introduce undefined behavior. // In addition, we may sink instructions that produce %c or %d from // the entry block into the destination(s) of the new branch. // If the true or false blocks do not contain a sunken instruction, that @@ -6217,7 +6219,9 @@ TT = TrueBlock; FT = FalseBlock; } - IRBuilder<>(SI).CreateCondBr(SI->getCondition(), TT, FT, SI); + IRBuilder<> IB(SI); + auto CondFr = IB.CreateFreeze(SI->getCondition(), SI->getName() + ".fr"); + IB.CreateCondBr(CondFr, TT, FT, SI); SmallPtrSet INS; INS.insert(ASI.begin(), ASI.end()); diff --git a/llvm/test/CodeGen/ARM/2012-08-30-select.ll b/llvm/test/CodeGen/ARM/2012-08-30-select.ll --- a/llvm/test/CodeGen/ARM/2012-08-30-select.ll +++ b/llvm/test/CodeGen/ARM/2012-08-30-select.ll @@ -2,9 +2,9 @@ ; rdar://12201387 ;CHECK-LABEL: select_s_v_v: +;CHECK: vmov.i32 ;CHECK: vmov ;CHECK-NEXT: vmov -;CHECK: vmov.i32 ;CHECK: bx define <16 x i8> @select_s_v_v(<16 x i8> %vec, i32 %avail) { entry: diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/optimizeSelect-DT.ll b/llvm/test/Transforms/CodeGenPrepare/X86/optimizeSelect-DT.ll --- a/llvm/test/Transforms/CodeGenPrepare/X86/optimizeSelect-DT.ll +++ b/llvm/test/Transforms/CodeGenPrepare/X86/optimizeSelect-DT.ll @@ -7,7 +7,8 @@ define i1 @PR41004(i32 %x, i32 %y, i32 %t1) { ; CHECK-LABEL: @PR41004( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[T0:%.*]] = icmp eq i32 [[Y:%.*]], 1 +; CHECK-NEXT: [[MUL_FR:%.*]] = freeze i32 [[Y:%.*]] +; CHECK-NEXT: [[T0:%.*]] = icmp eq i32 [[MUL_FR]], 1 ; CHECK-NEXT: br i1 [[T0]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END:%.*]] ; CHECK: select.true.sink: ; CHECK-NEXT: [[REM:%.*]] = srem i32 [[X:%.*]], 2 diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/select.ll b/llvm/test/Transforms/CodeGenPrepare/X86/select.ll --- a/llvm/test/Transforms/CodeGenPrepare/X86/select.ll +++ b/llvm/test/Transforms/CodeGenPrepare/X86/select.ll @@ -27,7 +27,8 @@ define float @fdiv_true_sink(float %a, float %b) { ; CHECK-LABEL: @fdiv_true_sink( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 1.000000e+00 +; CHECK-NEXT: [[SEL_FR:%.*]] = freeze float [[A:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[SEL_FR]], 1.000000e+00 ; CHECK-NEXT: br i1 [[CMP]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END:%.*]] ; CHECK: select.true.sink: ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[A]], [[B:%.*]] @@ -38,7 +39,8 @@ ; ; DEBUG-LABEL: @fdiv_true_sink( ; DEBUG-NEXT: entry: -; DEBUG-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 1.000000e+00 +; DEBUG-NEXT: [[SEL_FR:%.*]] = freeze float [[A:%.*]] +; DEBUG-NEXT: [[CMP:%.*]] = fcmp ogt float [[SEL_FR]], 1.000000e+00, !dbg !24 ; DEBUG-NEXT: call void @llvm.dbg.value(metadata i1 [[CMP]] ; DEBUG-NEXT: br i1 [[CMP]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END:%.*]], !dbg ; DEBUG: select.true.sink: @@ -60,7 +62,8 @@ define float @fdiv_false_sink(float %a, float %b) { ; CHECK-LABEL: @fdiv_false_sink( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 3.000000e+00 +; CHECK-NEXT: [[SEL_FR:%.*]] = freeze float [[A:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[SEL_FR]], 3.000000e+00 ; CHECK-NEXT: br i1 [[CMP]], label [[SELECT_END:%.*]], label [[SELECT_FALSE_SINK:%.*]] ; CHECK: select.false.sink: ; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[A]], [[B:%.*]] @@ -71,7 +74,8 @@ ; ; DEBUG-LABEL: @fdiv_false_sink( ; DEBUG-NEXT: entry: -; DEBUG-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 3.000000e+00 +; DEBUG-NEXT: [[SEL_FR:%.*]] = freeze float [[A:%.*]] +; DEBUG-NEXT: [[CMP:%.*]] = fcmp ogt float [[SEL_FR]], 3.000000e+00, !dbg !33 ; DEBUG-NEXT: call void @llvm.dbg.value(metadata i1 [[CMP]] ; DEBUG-NEXT: br i1 [[CMP]], label [[SELECT_END:%.*]], label [[SELECT_FALSE_SINK:%.*]], !dbg ; DEBUG: select.false.sink: @@ -93,7 +97,8 @@ define float @fdiv_both_sink(float %a, float %b) { ; CHECK-LABEL: @fdiv_both_sink( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 5.000000e+00 +; CHECK-NEXT: [[SEL_FR:%.*]] = freeze float [[A:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[SEL_FR]], 5.000000e+00 ; CHECK-NEXT: br i1 [[CMP]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_FALSE_SINK:%.*]] ; CHECK: select.true.sink: ; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[A]], [[B:%.*]]