We can support ashr similar to lshr, if we know that none of the shifted in bits are used. In that case SimplifyDemandedBits would normally convert it to lshr. But that conversion doesn't happen if the shift has additional users.
Here are the alive tests I used to prove this
Name: test1 Pre: ((C3 << C1) u>> C1) == C3 && ((C2 << C1) u>> C1) == C2 %a = ashr %x, C1 %b = and %a, C2 %c = icmp eq %b, C3 => %d = and %x, C2 << C1 %c = icmp eq %d, C3 << C1 Name: test2 Pre: ((C3 << C1) u>> C1) == C3 && ((C2 << C1) u>> C1) == C2 %a = ashr %x, C1 %b = and %a, C2 %c = icmp ult %b, C3 => %d = and %x, C2 << C1 %c = icmp ult %d, C3 << C1 Name: test3 Pre: ((C3 << C1) u>> C1) == C3 && ((C2 << C1) u>> C1) == C2 %a = ashr %x, C1 %b = and %a, C2 %c = icmp ugt %b, C3 => %d = and %x, C2 << C1 %c = icmp ugt %d, C3 << C1 Name: test4 Pre: ((C3 << C1) u>> C1) == C3 && ((C2 << C1) u>> C1) == C2 %a = ashr %x, C1 %b = and %a, C2 %c = icmp uge %b, C3 => %d = and %x, C2 << C1 %c = icmp uge %d, C3 << C1 Name: test5 Pre: ((C3 << C1) u>> C1) == C3 && ((C2 << C1) u>> C1) == C2 %a = ashr %x, C1 %b = and %a, C2 %c = icmp ule %b, C3 => %d = and %x, C2 << C1 %c = icmp ule %d, C3 << C1 Name: test6 Pre: ((C3 << C1) u>> C1) == C3 && ((C2 << C1) u>> C1) == C2 %a = ashr %x, C1 %b = and %a, C2 %c = icmp ne %b, C3 => %d = and %x, C2 << C1 %c = icmp ne %d, C3 << C1 Name: test7 Pre: ((C1 << C3) u>> C3) == C1 && ((C2 << C3) u>> C3) == C2 && (C2 << C3) >= 0 && (C1 << C3) >= 0 %a = ashr %x, C3 %b = and %a, C2 %c = icmp sgt %b, C1 => %d = and %x, C2 << C3 %c = icmp sgt %d, C1 << C3 Name: test8 Pre: ((C1 << C3) u>> C3) == C1 && ((C2 << C3) u>> C3) == C2 && (C2 << C3) >= 0 && (C1 << C3) >= 0 %a = ashr %x, C3 %b = and %a, C2 %c = icmp slt %b, C1 => %d = and %x, C2 << C3 %c = icmp slt %d, C1 << C3 `