@@ -125,7 +125,7 @@ fn parse(output: &str) -> HashSet<Function> {
125125 cached_header = None ;
126126 break ;
127127 }
128- let parts = if cfg ! ( target_env = "msvc" ) {
128+ let mut parts = if cfg ! ( target_env = "msvc" ) {
129129 // Each line looks like:
130130 //
131131 // > $addr: ab cd ef $instr..
@@ -152,6 +152,31 @@ fn parse(output: &str) -> HashSet<Function> {
152152 . map ( std:: string:: ToString :: to_string)
153153 . collect :: < Vec < String > > ( )
154154 } ;
155+
156+ if cfg ! ( target_arch = "aarch64" ) {
157+ // Normalize [us]shll.* ..., #0 instructions to the preferred form: [us]xtl.* ...
158+ // as LLVM objdump does not do that.
159+ // See https://developer.arm.com/documentation/ddi0602/latest/SIMD-FP-Instructions/UXTL--UXTL2--Unsigned-extend-Long--an-alias-of-USHLL--USHLL2-
160+ // and https://developer.arm.com/documentation/ddi0602/latest/SIMD-FP-Instructions/SXTL--SXTL2--Signed-extend-Long--an-alias-of-SSHLL--SSHLL2-
161+ // for details.
162+ match ( parts. first ( ) , parts. last ( ) ) {
163+ ( Some ( instr) , Some ( last_arg) )
164+ if ( instr. starts_with ( "ushll." ) || instr. starts_with ( "sshll." ) )
165+ && last_arg == "#0" =>
166+ {
167+ assert_eq ! ( parts. len( ) , 4 ) ;
168+ let mut new_parts = Vec :: with_capacity ( 3 ) ;
169+ let mut new_instr = instr[ ..1 ] . to_owned ( ) ;
170+ new_instr. push_str ( "xtl" ) ;
171+ new_instr. push_str ( & instr[ 5 ..] ) ;
172+ new_parts. push ( new_instr) ;
173+ new_parts. push ( parts[ 1 ] . clone ( ) ) ;
174+ new_parts. push ( parts[ 2 ] [ 0 ..parts[ 2 ] . len ( ) - 1 ] . to_owned ( ) ) ; // strip trailing comma
175+ parts = new_parts;
176+ }
177+ _ => { }
178+ } ;
179+ }
155180 instructions. push ( parts. join ( " " ) ) ;
156181 }
157182 let function = Function {
0 commit comments