if (!isa<Instruction>(V))
return false;
+ if (isa<SExtInst>(V))
+ return true;
+
unsigned Opc = cast<Instruction>(V)->getOpcode();
return Opc == Instruction::AShr || Opc == Instruction::SDiv ||
Opc == Instruction::SRem;
static bool isSource(Value *V) {
if (!isa<IntegerType>(V->getType()))
return false;
- // TODO Allow zext to be sources.
- if (isa<Argument>(V))
- return true;
- else if (isa<LoadInst>(V))
- return true;
- else if (isa<BitCastInst>(V))
+ else if (isa<Argument>(V) || isa<LoadInst>(V) || isa<CallInst>(V))
return true;
- else if (auto *Call = dyn_cast<CallInst>(V))
- return Call->hasRetAttr(Attribute::AttrKind::ZExt);
- else if (auto *Trunc = dyn_cast<TruncInst>(V))
- return isSupportedType(Trunc);
+ else if (isa<CastInst>(V))
+ return isSupportedType(V);
return false;
}
/// return value is zeroext. We don't allow opcodes that can introduce sign
/// bits.
bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
- if (isa<ICmpInst>(V))
- return true;
+ if (generateSignBits(V))
+ return false;
- // Memory instructions
- if (isa<StoreInst>(V) || isa<GetElementPtrInst>(V))
- return true;
+ // Disallow for simplicity.
+ if (isa<ConstantExpr>(V))
+ return false;
- // Branches and targets.
- if( isa<BranchInst>(V) || isa<SwitchInst>(V) || isa<BasicBlock>(V))
+ // Special case because they generate an i1, which we don't generally
+ // support.
+ if (isa<ICmpInst>(V))
return true;
- // Non-instruction values that we can handle.
- if ((isa<Constant>(V) && !isa<ConstantExpr>(V)) || isa<Argument>(V))
- return isSupportedType(V);
-
- if (isa<PHINode>(V) || isa<SelectInst>(V) || isa<ReturnInst>(V) ||
- isa<LoadInst>(V))
- return isSupportedType(V);
-
- // Truncs can be either sources or sinks.
- if (auto *Trunc = dyn_cast<TruncInst>(V))
- return isSupportedType(Trunc) || isSupportedType(Trunc->getOperand(0));
-
- if (isa<CastInst>(V) && !isa<SExtInst>(V))
- return isSupportedType(cast<CastInst>(V)->getOperand(0));
+ // Both ZExts and Truncs can be either sources and sinks. BitCasts are also
+ // sources and SExts are disallowed through their sign bit generation.
+ if (auto *Cast = dyn_cast<CastInst>(V))
+ return isSupportedType(Cast) || isSupportedType(Cast->getOperand(0));
// Special cases for calls as we need to check for zeroext
// TODO We should accept calls even if they don't have zeroext, as they can
return isSupportedType(Call) &&
Call->hasRetAttr(Attribute::AttrKind::ZExt);
- if (!isa<BinaryOperator>(V))
- return false;
-
- if (!isSupportedType(V))
- return false;
-
- if (generateSignBits(V)) {
- LLVM_DEBUG(dbgs() << "ARM CGP: No, instruction can generate sign bits.\n");
- return false;
- }
- return true;
+ return isSupportedType(V);
}
/// Check that the type of V would be promoted and that the original type is
ret i8 %2
}
+; TODO: We should be able to remove both extends from this example, by looking
+; back through the zexts and accepting a type size <= than the icmp.
+; CHECK-COMMON-LABEL: icmp_i16_zext
+; CHECK-COMMON: uxt
+; CHECK-COMMON: uxt
+define i8 @icmp_i16_zext(i8* %ptr) {
+entry:
+ %gep = getelementptr inbounds i8, i8* %ptr, i32 0
+ %0 = load i8, i8* %gep, align 1
+ %1 = sub nuw nsw i8 %0, 1
+ %conv44 = zext i8 %0 to i16
+ br label %preheader
+
+preheader:
+ br label %body
+
+body:
+ %2 = phi i8 [ %1, %preheader ], [ %3, %if.end ]
+ %si.0274 = phi i16 [ %conv44, %preheader ], [ %inc, %if.end ]
+ %conv51266 = zext i8 %2 to i16
+ %cmp52267 = icmp eq i16 %si.0274, %conv51266
+ br i1 %cmp52267, label %if.end, label %exit
+
+if.end:
+ %inc = add nuw i16 %si.0274, 1
+ %conv = zext i16 %inc to i32
+ %gep1 = getelementptr inbounds i8, i8* %ptr, i32 %conv
+ %3 = load i8, i8* %gep1, align 1
+ br label %body
+
+exit:
+ ret i8 %2
+}
+
; Won't don't handle sext
; CHECK-COMMON-LABEL: icmp_sext_zext_store_i8_i16
; CHECK-COMMON: ldrb