[cfe-commits] [PATCH][review request] Add support for LLVM intrinsic bswap16
James Orr
jorr at apple.com
Sat Mar 19 20:02:26 PDT 2011
On Mar 19, 2011, at 7:25 PM, Chris Lattner wrote:
>
> On Mar 19, 2011, at 3:24 PM, Eli Friedman wrote:
>
>> On Sat, Mar 19, 2011 at 3:15 PM, James Orr <jorr at apple.com> wrote:
>>> Add support for built in 16bit byte swap.
>>
>> Why?
>
> Yes, why? GCC doesn't support this either IIRC.
>
> -Chris
I want to convert a big endian short to little endian (ie Cortex-M0 reading over I2C a 16bit ADC value returned in big endian).
Clang does not recognize the following as a byte swap: (uint16_t)( a >> 8) | (uint16_t)( a << 8); (llvm-gcc does)
In the ARM architecture this can be accomplished with single instruction (REV16, or in the case I really care about REVSH)
Even with this patch LLVM generates two instructions: REV (which is 32 bit byte swap) and LSRS. But now the LLVM representation looks better:
// using intrinsic
define zeroext i16 @bswapI(i16 zeroext %a) nounwind readnone optsize ssp {
%1 = tail call i16 @llvm.bswap.i16(i16 %a)
ret i16 %1
}
declare i16 @llvm.bswap.i16(i16) nounwind readnone
// C - code
define zeroext i16 @bswapC(i16 zeroext %a) nounwind readnone optsize ssp {
%1 = zext i16 %a to i32
%2 = lshr i16 %a, 8
%3 = zext i16 %2 to i32
%4 = shl nuw nsw i32 %1, 8
%5 = or i32 %3, %4
%6 = trunc i32 %5 to i16
ret i16 %6
}
I agree this should not be necessary if Clang be taught to recognize this itself, but I could not figure that out (yet). In the meantime this patch enables me to look into the LLVM half of generating the instructions.
I realize GCC only supports 32, and 64, but LLVM supports 16 as well and I did not see the harm in exposing it.
-James
>
>>
>> -Eli
>>
>>> -James
>>>
>>> Index: include/clang/Basic/Builtins.def
>>> ===================================================================
>>> --- include/clang/Basic/Builtins.def (revision 127948)
>>> +++ include/clang/Basic/Builtins.def (working copy)
>>> @@ -380,6 +380,7 @@
>>>
>>> // FIXME: These type signatures are not correct for targets with int != 32-bits
>>> // or with ULL != 64-bits.
>>> +BUILTIN(__builtin_bswap16, "UsUs", "nc")
>>> BUILTIN(__builtin_bswap32, "UiUi", "nc")
>>> BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
>>>
>>> Index: lib/CodeGen/CGBuiltin.cpp
>>> ===================================================================
>>> --- lib/CodeGen/CGBuiltin.cpp (revision 127948)
>>> +++ lib/CodeGen/CGBuiltin.cpp (working copy)
>>> @@ -316,6 +316,7 @@
>>> (void)EmitScalarExpr(E->getArg(1));
>>> return RValue::get(EmitScalarExpr(E->getArg(0)));
>>> }
>>> + case Builtin::BI__builtin_bswap16:
>>> case Builtin::BI__builtin_bswap32:
>>> case Builtin::BI__builtin_bswap64: {
>>> Value *ArgValue = EmitScalarExpr(E->getArg(0));
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list