There are 2 patterns for zero-extend as below.
//In the case of a 32-bit def that is known to implicitly zero-extend, //we can use a SUBREG_TO_REG. def : Pat<(i64 (zext def32:$src)), (SUBREG_TO_REG (i64 0), GPR32:$src, sub_32)>; //When we need to explicitly zero-extend, we use a 32-bit MOV instruction //and then assert the extension has happened. def : Pat<(i64 (zext GPR32:$src)), (SUBREG_TO_REG (i32 0), (ORRWrs WZR, GPR32:$src, 0), sub_32)>;
The def32 checks the $src needs explicitly zero-extend. However, it can not check the $src in other block and it adds ORRWrs conservatively in this case. This peephole optimization checks ORRWrs is for redundant zero-extend and try to remove it.
I don't think that representing this in terms of ISel patterns is useful. It should preferably be described in terms of the Machine Instructions that will be present, no matter where they come from.