Game loops can deploy mechanisms to prevent logic from not being executed if the other parts of the loop take too long. For example, if you'll lock your game logic at 30 frames per second and inside of the loop you check if it's the time to run the logic frame, then instead of putting it in an "if" statement, you put it in a loop that'll have a "max frame skip limit".
The idea is that if your game is going to render slowly then the next iteration the game logic will "catch up" by executing x amount of times instead of just 1.
If you have your bullet shooting tied to a timer then you can also put the logic that checks if it's the time to fire inside of a loop and just try to make up for frame rate drops.
Now, in general, this doesn't matter as much as you describe it. The player isn't REALLY at a disadvantage here. Everything needs to be processed inside of the game loop. If the player's gun doesn't fire, then the AI's gun doesn't fire aswell. So it's all about the implementation. Either you consider frame rate drops when dealing with AI and the player or neighter.