Skip to content

Commit 5019000

Browse files
author
Jan Voung
committed
Promote bswap i16, i32, and i64 to be allowed llvm intrinsics.
Disallow i1, i8, which don't make sense for "byte" swapping. None of these generate outcalls to compiler_rt. Test coverage: * test/CodeGen/AArch64/dp1.ll (only testing i32, i64) * test/CodeGen/ARM/rev.ll (only testing i16) * test/CodeGen/Mips/bswap.ll (only testing i32, i64) * test/CodeGen/X86/bswap.ll (i16, i32, i64, on i686) * test/NaCl/{ARM,X86}/intrinsics-bitmanip.ll (i16, i32, i64) (maybe the last set of tests could be merged into the upstream tests) For targets without native i16 bswap, the i16 could just be a bswap on an i32 plus a shift right 16. Other test coverage: * gcc/testsuite/gcc.dg/builtin-bswap-[1,2,3,4,5].c Misc: style cleanups, and add comments to the undocumented intrinsics in the dev list. BUG=https://code.google.com/p/nativeclient/issues/detail?id=3378 [email protected] Review URL: https://codereview.chromium.org/14914011
1 parent 9f0ec13 commit 5019000

File tree

2 files changed

+58
-14
lines changed

2 files changed

+58
-14
lines changed

lib/Analysis/NaCl/PNaClABIVerifyModule.cpp

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ class PNaClABIVerifyModule : public ModulePass {
6262
bool runOnModule(Module &M);
6363
virtual void print(raw_ostream &O, const Module *M) const;
6464
private:
65-
void CheckGlobalValueCommon(const GlobalValue *GV);
66-
bool IsWhitelistedIntrinsic(const Function* F, unsigned ID);
67-
bool IsWhitelistedMetadata(const NamedMDNode *MD);
65+
void checkGlobalValueCommon(const GlobalValue *GV);
66+
bool isWhitelistedIntrinsic(const Function *F, unsigned ID);
67+
bool isWhitelistedMetadata(const NamedMDNode *MD);
6868
PNaClABITypeChecker TC;
6969
PNaClABIErrorReporter *Reporter;
7070
bool ReporterIsOwned;
@@ -100,7 +100,7 @@ static const char *linkageName(GlobalValue::LinkageTypes LT) {
100100

101101
// Check linkage type and section attributes, which are the same for
102102
// GlobalVariables and Functions.
103-
void PNaClABIVerifyModule::CheckGlobalValueCommon(const GlobalValue *GV) {
103+
void PNaClABIVerifyModule::checkGlobalValueCommon(const GlobalValue *GV) {
104104
assert(!isa<GlobalAlias>(GV));
105105
const char *GVTypeName = isa<GlobalVariable>(GV) ?
106106
"Variable " : "Function ";
@@ -122,7 +122,32 @@ void PNaClABIVerifyModule::CheckGlobalValueCommon(const GlobalValue *GV) {
122122
}
123123
}
124124

125-
bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
125+
static bool TypeAcceptable(const Type *T,
126+
const ArrayRef<Type*> &AcceptableTypes) {
127+
for (ArrayRef<Type*>::iterator I = AcceptableTypes.begin(),
128+
E = AcceptableTypes.end(); I != E; ++I)
129+
if (*I == T)
130+
return true;
131+
return false;
132+
}
133+
134+
// We accept bswap for a limited set of types (i16, i32, i64).
135+
// The various backends are able to generate instructions to
136+
// implement the intrinsic. Also, i16 and i64 are easy to
137+
// implement as along as there is a way to do i32.
138+
static bool isWhitelistedBswap(const Function *F) {
139+
FunctionType *FT = F->getFunctionType();
140+
if (FT->getNumParams() != 1)
141+
return false;
142+
Type *ParamType = FT->getParamType(0);
143+
LLVMContext &C = F->getContext();
144+
Type *AcceptableTypes[] = { Type::getInt16Ty(C),
145+
Type::getInt32Ty(C),
146+
Type::getInt64Ty(C) };
147+
return TypeAcceptable(ParamType, AcceptableTypes);
148+
}
149+
150+
bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F,
126151
unsigned ID) {
127152
// Keep 3 categories of intrinsics for now.
128153
// (1) Allowed always
@@ -135,6 +160,7 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
135160
// Disallow by default.
136161
default: return false;
137162
// (1) Always allowed.
163+
case Intrinsic::bswap: return isWhitelistedBswap(F);
138164
case Intrinsic::invariant_end:
139165
case Intrinsic::invariant_start:
140166
case Intrinsic::lifetime_end:
@@ -179,15 +205,16 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
179205
case Intrinsic::dbg_declare:
180206
case Intrinsic::dbg_value:
181207
return PNaClABIAllowDevIntrinsics || PNaClABIAllowDebugMetadata;
182-
case Intrinsic::bswap: // Support via compiler_rt if arch doesn't have it?
183208
case Intrinsic::cos: // Rounding not defined: support with fast-math?
184209
case Intrinsic::ctlz: // Support via compiler_rt if arch doesn't have it?
185210
case Intrinsic::ctpop: // Support via compiler_rt if arch doesn't have it?
186211
case Intrinsic::cttz: // Support via compiler_rt if arch doesn't have it?
187212
case Intrinsic::exp: // Rounding not defined: support with fast-math?
188213
case Intrinsic::exp2: // Rounding not defined: support with fast-math?
189214
case Intrinsic::expect: // From __builtin_expect.
190-
case Intrinsic::flt_rounds:
215+
case Intrinsic::flt_rounds: // For FLT_ROUNDS macro from float.h.
216+
// We do not have fesetround() in newlib, can we return a
217+
// consistent rounding mode though?
191218
case Intrinsic::log: // Rounding not defined: support with fast-math?
192219
case Intrinsic::log2: // Rounding not defined: support with fast-math?
193220
case Intrinsic::log10: // Rounding not defined: support with fast-math?
@@ -196,9 +223,9 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
196223
case Intrinsic::powi: // Rounding not defined: support with fast-math?
197224
case Intrinsic::prefetch: // Could ignore if target doesn't support?
198225
case Intrinsic::sin: // Rounding not defined: support with fast-math?
199-
case Intrinsic::sqrt:
226+
case Intrinsic::sqrt: // Rounding is defined, but setting errno up to libm.
200227
case Intrinsic::stackrestore: // Used to support C99 VLAs.
201-
case Intrinsic::stacksave:
228+
case Intrinsic::stacksave: // Used to support C99 VLAs.
202229
// the *_with_overflow return struct types, so we'll need to fix these.
203230
case Intrinsic::sadd_with_overflow: // Introduced by -ftrapv
204231
case Intrinsic::ssub_with_overflow:
@@ -210,7 +237,7 @@ bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
210237
}
211238
}
212239

213-
bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) {
240+
bool PNaClABIVerifyModule::isWhitelistedMetadata(const NamedMDNode *MD) {
214241
return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata;
215242
}
216243

@@ -234,7 +261,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
234261
}
235262
}
236263

237-
CheckGlobalValueCommon(MI);
264+
checkGlobalValueCommon(MI);
238265

239266
if (MI->isThreadLocal()) {
240267
Reporter->addError() << "Variable " << MI->getName() <<
@@ -252,7 +279,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
252279
for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
253280
// Check intrinsics.
254281
if (MI->isIntrinsic()
255-
&& !IsWhitelistedIntrinsic(MI, MI->getIntrinsicID())) {
282+
&& !isWhitelistedIntrinsic(MI, MI->getIntrinsicID())) {
256283
Reporter->addError() << "Function " << MI->getName()
257284
<< " is a disallowed LLVM intrinsic\n";
258285
}
@@ -279,7 +306,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
279306
" is a variable-argument function (disallowed)\n";
280307
}
281308

282-
CheckGlobalValueCommon(MI);
309+
checkGlobalValueCommon(MI);
283310

284311
if (MI->hasGC()) {
285312
Reporter->addError() << "Function " << MI->getName() <<
@@ -290,7 +317,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
290317
// Check named metadata nodes
291318
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
292319
E = M.named_metadata_end(); I != E; ++I) {
293-
if (!IsWhitelistedMetadata(I)) {
320+
if (!isWhitelistedMetadata(I)) {
294321
Reporter->addError() << "Named metadata node " << I->getName()
295322
<< " is disallowed\n";
296323
} else {

test/NaCl/PNaClABI/intrinsics.ll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ declare void @llvm.lifetime.start(i64, i8* nocapture)
2828

2929
; CHECK-NOT: Function llvm.lifetime.start is a disallowed LLVM intrinsic
3030
declare void @llvm.lifetime.end(i64, i8* nocapture)
31+
3132
; CHECK-NOT: Function llvm.memcpy.p0i8.p0i8.i32 is a disallowed LLVM intrinsic
3233
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src,
3334
i32 %len, i32 %align, i1 %isvolatile)
@@ -37,8 +38,18 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src,
3738
; CHECK-NOT: Function llvm.nacl.read.tp is a disallowed LLVM intrinsic
3839
declare i8* @llvm.nacl.read.tp()
3940

41+
; CHECK-NOT: Function llvm.bswap.16 is a disallowed LLVM intrinsic
42+
declare i16 @llvm.bswap.16(i16)
43+
44+
; CHECK-NOT: Function llvm.bswap.32 is a disallowed LLVM intrinsic
45+
declare i32 @llvm.bswap.32(i32)
46+
47+
; CHECK-NOT: Function llvm.bswap.64 is a disallowed LLVM intrinsic
48+
declare i64 @llvm.bswap.64(i64)
49+
4050
; ===================================
4151
; Always disallowed intrinsics.
52+
4253
; CHECK: Function llvm.adjust.trampoline is a disallowed LLVM intrinsic
4354
; DBG: Function llvm.adjust.trampoline is a disallowed LLVM intrinsic
4455
; DEV: Function llvm.adjust.trampoline is a disallowed LLVM intrinsic
@@ -58,3 +69,9 @@ declare <2 x i64> @llvm.x86.aesni.aeskeygenassist(<2 x i64>, i8)
5869
; DBG: Function llvm.va_copy is a disallowed LLVM intrinsic
5970
; DEV: Function llvm.va_copy is a disallowed LLVM intrinsic
6071
declare void @llvm.va_copy(i8*, i8*)
72+
73+
; CHECK: Function llvm.bswap.1 is a disallowed LLVM intrinsic
74+
declare i1 @llvm.bswap.1(i1)
75+
76+
; CHECK: Function llvm.bswap.8 is a disallowed LLVM intrinsic
77+
declare i8 @llvm.bswap.8(i8)

0 commit comments

Comments
 (0)