[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