Index: lib/Target/ARM/ARMCodeGenPrepare.cpp =================================================================== --- lib/Target/ARM/ARMCodeGenPrepare.cpp +++ lib/Target/ARM/ARMCodeGenPrepare.cpp @@ -165,6 +165,9 @@ if (!isa(V)) return false; + if (isa(V)) + return true; + unsigned Opc = cast(V)->getOpcode(); return Opc == Instruction::AShr || Opc == Instruction::SDiv || Opc == Instruction::SRem; @@ -201,17 +204,10 @@ static bool isSource(Value *V) { if (!isa(V->getType())) return false; - // TODO Allow zext to be sources. - if (isa(V)) - return true; - else if (isa(V)) - return true; - else if (isa(V)) + else if (isa(V) || isa(V) || isa(V)) return true; - else if (auto *Call = dyn_cast(V)) - return Call->hasRetAttr(Attribute::AttrKind::ZExt); - else if (auto *Trunc = dyn_cast(V)) - return isSupportedType(Trunc); + else if (isa(V)) + return isSupportedType(V); return false; } @@ -515,31 +511,22 @@ /// return value is zeroext. We don't allow opcodes that can introduce sign /// bits. bool ARMCodeGenPrepare::isSupportedValue(Value *V) { - if (isa(V)) - return true; + if (generateSignBits(V)) + return false; - // Memory instructions - if (isa(V) || isa(V)) - return true; + // Disallow for simplicity. + if (isa(V)) + return false; - // Branches and targets. - if( isa(V) || isa(V) || isa(V)) + // Special case because they generate an i1, which we don't generally + // support. + if (isa(V)) return true; - // Non-instruction values that we can handle. - if ((isa(V) && !isa(V)) || isa(V)) - return isSupportedType(V); - - if (isa(V) || isa(V) || isa(V) || - isa(V)) - return isSupportedType(V); - - // Truncs can be either sources or sinks. - if (auto *Trunc = dyn_cast(V)) - return isSupportedType(Trunc) || isSupportedType(Trunc->getOperand(0)); - - if (isa(V) && !isa(V)) - return isSupportedType(cast(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(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 @@ -548,17 +535,7 @@ return isSupportedType(Call) && Call->hasRetAttr(Attribute::AttrKind::ZExt); - if (!isa(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 Index: test/CodeGen/ARM/arm-cgp-casts.ll =================================================================== --- test/CodeGen/ARM/arm-cgp-casts.ll +++ test/CodeGen/ARM/arm-cgp-casts.ll @@ -85,6 +85,40 @@ 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