@@ -2674,7 +2674,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
26742674 const llvm::ArrayRef<LValue> ResultRegDests,
26752675 const llvm::ArrayRef<QualType> ResultRegQualTys,
26762676 const llvm::BitVector &ResultTypeRequiresCast,
2677- const llvm::BitVector &ResultRegIsFlagReg) {
2677+ const std::vector<std::optional<std::pair<unsigned , unsigned >>>
2678+ &ResultBounds) {
26782679 CGBuilderTy &Builder = CGF.Builder ;
26792680 CodeGenModule &CGM = CGF.CGM ;
26802681 llvm::LLVMContext &CTX = CGF.getLLVMContext ();
@@ -2685,18 +2686,20 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
26852686 // ResultRegDests can be also populated by addReturnRegisterOutputs() above,
26862687 // in which case its size may grow.
26872688 assert (ResultTypeRequiresCast.size () <= ResultRegDests.size ());
2688- assert (ResultRegIsFlagReg .size () <= ResultRegDests.size ());
2689+ assert (ResultBounds .size () <= ResultRegDests.size ());
26892690
26902691 for (unsigned i = 0 , e = RegResults.size (); i != e; ++i) {
26912692 llvm::Value *Tmp = RegResults[i];
26922693 llvm::Type *TruncTy = ResultTruncRegTypes[i];
26932694
2694- if ((i < ResultRegIsFlagReg.size ()) && ResultRegIsFlagReg[i]) {
2695- // Target must guarantee the Value `Tmp` here is lowered to a boolean
2696- // value.
2697- llvm::Constant *Two = llvm::ConstantInt::get (Tmp->getType (), 2 );
2695+ if ((i < ResultBounds.size ()) && ResultBounds[i].has_value ()) {
2696+ const auto [LowerBound, UpperBound] = ResultBounds[i].value ();
2697+ // FIXME: Support for nonzero lower bounds not yet implemented.
2698+ assert (LowerBound == 0 && " Output operand lower bound is not zero." );
2699+ llvm::Constant *UpperBoundConst =
2700+ llvm::ConstantInt::get (Tmp->getType (), UpperBound);
26982701 llvm::Value *IsBooleanValue =
2699- Builder.CreateCmp (llvm::CmpInst::ICMP_ULT, Tmp, Two );
2702+ Builder.CreateCmp (llvm::CmpInst::ICMP_ULT, Tmp, UpperBoundConst );
27002703 llvm::Function *FnAssume = CGM.getIntrinsic (llvm::Intrinsic::assume);
27012704 Builder.CreateCall (FnAssume, IsBooleanValue);
27022705 }
@@ -2825,7 +2828,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
28252828 std::vector<llvm::Type *> ArgElemTypes;
28262829 std::vector<llvm::Value*> Args;
28272830 llvm::BitVector ResultTypeRequiresCast;
2828- llvm::BitVector ResultRegIsFlagReg ;
2831+ std::vector<std::optional<std::pair< unsigned , unsigned >>> ResultBounds ;
28292832
28302833 // Keep track of inout constraints.
28312834 std::string InOutConstraints;
@@ -2883,8 +2886,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
28832886 ResultRegQualTys.push_back (QTy);
28842887 ResultRegDests.push_back (Dest);
28852888
2886- bool IsFlagReg = llvm::StringRef (OutputConstraint).starts_with (" {@cc" );
2887- ResultRegIsFlagReg.push_back (IsFlagReg);
2889+ ResultBounds.emplace_back (Info.getOutputOperandBounds ());
28882890
28892891 llvm::Type *Ty = ConvertTypeForMem (QTy);
28902892 const bool RequiresCast = Info.allowsRegister () &&
@@ -3231,7 +3233,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
32313233
32323234 EmitAsmStores (*this , S, RegResults, ResultRegTypes, ResultTruncRegTypes,
32333235 ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
3234- ResultRegIsFlagReg );
3236+ ResultBounds );
32353237
32363238 // If this is an asm goto with outputs, repeat EmitAsmStores, but with a
32373239 // different insertion point; one for each indirect destination and with
@@ -3242,7 +3244,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
32423244 Builder.SetInsertPoint (Succ, --(Succ->end ()));
32433245 EmitAsmStores (*this , S, CBRRegResults[Succ], ResultRegTypes,
32443246 ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
3245- ResultTypeRequiresCast, ResultRegIsFlagReg );
3247+ ResultTypeRequiresCast, ResultBounds );
32463248 }
32473249 }
32483250}
0 commit comments