@@ -148,6 +148,24 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> {
148148 }
149149 }
150150 }
151+
152+ // Generate sideeffect intrinsic if jumping to any of the targets can form
153+ // a loop.
154+ fn maybe_sideeffect < ' b , ' tcx2 : ' b , Bx : BuilderMethods < ' b , ' tcx2 > > (
155+ & self ,
156+ mir : & ' b mir:: Body < ' tcx > ,
157+ bx : & mut Bx ,
158+ targets : & [ mir:: BasicBlock ] ,
159+ ) {
160+ if targets. iter ( ) . any ( |target| {
161+ * target <= * self . bb
162+ && target
163+ . start_location ( )
164+ . is_predecessor_of ( self . bb . start_location ( ) , mir)
165+ } ) {
166+ bx. sideeffect ( ) ;
167+ }
168+ }
151169}
152170
153171/// Codegen implementations for some terminator variants.
@@ -196,6 +214,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
196214 let lltrue = helper. llblock ( self , targets[ 0 ] ) ;
197215 let llfalse = helper. llblock ( self , targets[ 1 ] ) ;
198216 if switch_ty == bx. tcx ( ) . types . bool {
217+ helper. maybe_sideeffect ( self . mir , & mut bx, targets. as_slice ( ) ) ;
199218 // Don't generate trivial icmps when switching on bool
200219 if let [ 0 ] = values[ ..] {
201220 bx. cond_br ( discr. immediate ( ) , llfalse, lltrue) ;
@@ -209,9 +228,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
209228 ) ;
210229 let llval = bx. const_uint_big ( switch_llty, values[ 0 ] ) ;
211230 let cmp = bx. icmp ( IntPredicate :: IntEQ , discr. immediate ( ) , llval) ;
231+ helper. maybe_sideeffect ( self . mir , & mut bx, targets. as_slice ( ) ) ;
212232 bx. cond_br ( cmp, lltrue, llfalse) ;
213233 }
214234 } else {
235+ helper. maybe_sideeffect ( self . mir , & mut bx, targets. as_slice ( ) ) ;
215236 let ( otherwise, targets) = targets. split_last ( ) . unwrap ( ) ;
216237 bx. switch (
217238 discr. immediate ( ) ,
@@ -310,6 +331,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
310331
311332 if let ty:: InstanceDef :: DropGlue ( _, None ) = drop_fn. def {
312333 // we don't actually need to drop anything.
334+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
313335 helper. funclet_br ( self , & mut bx, target) ;
314336 return
315337 }
@@ -340,6 +362,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
340362 FnType :: of_instance ( & bx, drop_fn) )
341363 }
342364 } ;
365+ bx. sideeffect ( ) ;
343366 helper. do_call ( self , & mut bx, fn_ty, drop_fn, args,
344367 Some ( ( ReturnDest :: Nothing , target) ) ,
345368 unwind) ;
@@ -375,6 +398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
375398
376399 // Don't codegen the panic block if success if known.
377400 if const_cond == Some ( expected) {
401+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
378402 helper. funclet_br ( self , & mut bx, target) ;
379403 return ;
380404 }
@@ -385,6 +409,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
385409 // Create the failure block and the conditional branch to it.
386410 let lltarget = helper. llblock ( self , target) ;
387411 let panic_block = self . new_block ( "panic" ) ;
412+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
388413 if expected {
389414 bx. cond_br ( cond, lltarget, panic_block. llbb ( ) ) ;
390415 } else {
@@ -437,6 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
437462 let fn_ty = FnType :: of_instance ( & bx, instance) ;
438463 let llfn = bx. get_fn ( instance) ;
439464
465+ bx. sideeffect ( ) ;
440466 // Codegen the actual panic invoke/call.
441467 helper. do_call ( self , & mut bx, fn_ty, llfn, & args, None , cleanup) ;
442468 }
@@ -488,6 +514,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
488514 if let Some ( destination_ref) = destination. as_ref ( ) {
489515 let & ( ref dest, target) = destination_ref;
490516 self . codegen_transmute ( & mut bx, & args[ 0 ] , dest) ;
517+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
491518 helper. funclet_br ( self , & mut bx, target) ;
492519 } else {
493520 // If we are trying to transmute to an uninhabited type,
@@ -518,6 +545,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
518545 Some ( ty:: InstanceDef :: DropGlue ( _, None ) ) => {
519546 // Empty drop glue; a no-op.
520547 let & ( _, target) = destination. as_ref ( ) . unwrap ( ) ;
548+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
521549 helper. funclet_br ( self , & mut bx, target) ;
522550 return ;
523551 }
@@ -554,6 +582,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
554582 let fn_ty = FnType :: of_instance ( & bx, instance) ;
555583 let llfn = bx. get_fn ( instance) ;
556584
585+ bx. sideeffect ( ) ;
557586 // Codegen the actual panic invoke/call.
558587 helper. do_call (
559588 self ,
@@ -566,7 +595,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
566595 ) ;
567596 } else {
568597 // a NOP
569- helper. funclet_br ( self , & mut bx, destination. as_ref ( ) . unwrap ( ) . 1 )
598+ let target = destination. as_ref ( ) . unwrap ( ) . 1 ;
599+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
600+ helper. funclet_br ( self , & mut bx, target) ;
570601 }
571602 return ;
572603 }
@@ -675,6 +706,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
675706 }
676707
677708 if let Some ( ( _, target) ) = * destination {
709+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
678710 helper. funclet_br ( self , & mut bx, target) ;
679711 } else {
680712 bx. unreachable ( ) ;
@@ -786,6 +818,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
786818 _ => span_bug ! ( span, "no llfn for call" ) ,
787819 } ;
788820
821+ bx. sideeffect ( ) ;
789822 helper. do_call ( self , & mut bx, fn_ty, fn_ptr, & llargs,
790823 destination. as_ref ( ) . map ( |& ( _, target) | ( ret_dest, target) ) ,
791824 cleanup) ;
@@ -835,6 +868,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
835868 }
836869
837870 mir:: TerminatorKind :: Goto { target } => {
871+ helper. maybe_sideeffect ( self . mir , & mut bx, & [ target] ) ;
838872 helper. funclet_br ( self , & mut bx, target) ;
839873 }
840874
0 commit comments