What's wrong with infinite loops inside loop()?
First, I will give you some unsolicited advise about your coding style.
Instead of writing:

PORTB &amp;= B11111110;
...
PORTB |= B00000001;


you could write:

PORTB &amp;= ~_BV(PB0);
...
PORTB |= _BV(PB0);


These are standard AVR idioms, and they make it clearer that you are
toggling the pin PB0.

Then, to answer your actual question, your delay loop does not work
because it got optimized-out by the compiler. This has already been said
in Michel Keijzers' answer, but let me elaborate.

All modern compilers are optimizing compilers. This means they can
change your code in whatever way they see fit, as long as the visible
effects remain the same. The effects considered visible are usually
I/O and access to variables declared volatile. Quite importantly, the
slowness of the program is not considered a visible effect for the
purpose of optimization. And if you think about it, it makes good sense:
if the slowness of the program were to be preserved, then any form of
optimization would be impossible. Thus, a loop that has no effect other
than slowing your program down can legitimately be optimized-out.

The solution to your problem is quite simple: if you want a delay, then
call delayMicroseconds(). Or maybe even delay() if you are OK with
its low resolution. On the other hand, if you need sub-microsecond
resolution, you can call _delay_us(), from the avr-libc. This function
(or rather, macro) provides single-cycle resolution. If you write

#include &lt;util/delay.h&gt;

...
_delay_us(1.375);


you get exactly what you ask for, i.e. a delay of 22&nbsp;CPU cycles
(on an Arduino Uno clocked at 16&nbsp;MHz). The issues with this
function are that it is AVR-specific, and its argument must be a
compile-time constant.

It has been suggested to you to write your delay loop using a volatile
loop counter. I strongly advise you against doing that, for three
reasons:


Doing so will force the counter to be allocated to RAM, thus
consuming a scarce and valuable resource for no good reason.
Incrementing a RAM-based 32-bit counter takes 20&nbsp;CPU cycles. Add
to this the time required to test the end-of-loop condition and you
will realize that your delay resolution is way worse than that of
delayMicroseconds().
Your actual delay will depend on the clock frequency, and probably
also on the compiler's version, making your code pretty fragile.