diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 59f1e07db555..21a0a85e12db 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -132,6 +132,9 @@ private: /// Translate a phi instruction. bool translatePHI(const User &U); + /// Translate an integer compare instruction (or constant). + bool translateICmp(const User &U); + /// Add remaining operands onto phis we've translated. Executed after all /// MachineBasicBlocks for the function have been created. void finishPendingPhis(); @@ -231,7 +234,6 @@ private: bool translateAddrSpaceCast(const User &U) { return false; } bool translateCleanupPad(const User &U) { return false; } bool translateCatchPad(const User &U) { return false; } - bool translateICmp(const User &U) { return false; } bool translateFCmp(const User &U) { return false; } bool translateSelect(const User &U) { return false; } bool translateUserOp1(const User &U) { return false; } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 2d84c3ef3776..0de9e2ad32ac 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -261,6 +261,14 @@ public: /// /// \return The newly created instruction. MachineInstrBuilder buildTrunc(LLT Ty, unsigned Res, unsigned Op); + + /// Build and insert either a G_ICMP + /// + /// \pre setBasicBlock or setMI must have been called. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildICmp(ArrayRef Tys, CmpInst::Predicate Pred, + unsigned Res, unsigned Op0, unsigned Op1); }; } // End namespace llvm. diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index 7119e0aa0f96..66aebcf64254 100644 --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -210,6 +210,11 @@ public: return *this; } + const MachineInstrBuilder &addPredicate(CmpInst::Predicate Pred) const { + MI->addOperand(*MF, MachineOperand::CreatePredicate(Pred)); + return *this; + } + const MachineInstrBuilder &addSym(MCSymbol *Sym, unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags)); diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h index b7569c07c49f..df143602a47c 100644 --- a/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/llvm/include/llvm/CodeGen/MachineOperand.h @@ -63,7 +63,8 @@ public: MO_Metadata, ///< Metadata reference (for debug info) MO_MCSymbol, ///< MCSymbol reference (for debug/eh info) MO_CFIIndex, ///< MCCFIInstruction index. - MO_IntrinsicID, ///< Intrinsic ID + MO_IntrinsicID, ///< Intrinsic ID for ISel + MO_Predicate, ///< Generic predicate for ISel }; private: @@ -164,6 +165,7 @@ private: MCSymbol *Sym; // For MO_MCSymbol. unsigned CFIIndex; // For MO_CFI. Intrinsic::ID IntrinsicID; // For MO_IntrinsicID. + unsigned Pred; // For MO_Predicate struct { // For MO_Register. // Register number is in SmallContents.RegNo. @@ -265,6 +267,7 @@ public: bool isMCSymbol() const { return OpKind == MO_MCSymbol; } bool isCFIIndex() const { return OpKind == MO_CFIIndex; } bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; } + bool isPredicate() const { return OpKind == MO_Predicate; } //===--------------------------------------------------------------------===// // Accessors for Register Operands //===--------------------------------------------------------------------===// @@ -464,6 +467,11 @@ public: return Contents.IntrinsicID; } + unsigned getPredicate() const { + assert(isPredicate() && "Wrong MachineOperand accessor"); + return Contents.Pred; + } + /// Return the offset from the symbol in this operand. This always returns 0 /// for ExternalSymbol operands. int64_t getOffset() const { @@ -749,6 +757,12 @@ public: return Op; } + static MachineOperand CreatePredicate(unsigned Pred) { + MachineOperand Op(MachineOperand::MO_Predicate); + Op.Contents.Pred = Pred; + return Op; + } + friend class MachineInstr; friend class MachineRegisterInfo; private: diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index effed02d0121..0abff7d1b8eb 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -957,6 +957,8 @@ public: return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; } + static StringRef getPredicateName(Predicate P); + bool isFPPredicate() const { return isFPPredicate(getPredicate()); } bool isIntPredicate() const { return isIntPredicate(getPredicate()); } diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 6a0243ab53fa..4221b82886e0 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -160,6 +160,13 @@ def G_ASHR : Instruction { let hasSideEffects = 0; } +// Generic bitwise or. +def G_ICMP : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$tst, unknown:$src1, unknown:$src2); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Memory ops //------------------------------------------------------------------------------ diff --git a/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def index 4fe56d021daa..9f485c6b5425 100644 --- a/llvm/include/llvm/Target/TargetOpcodes.def +++ b/llvm/include/llvm/Target/TargetOpcodes.def @@ -247,6 +247,9 @@ HANDLE_TARGET_OPCODE(G_LSHR) // Generic arithmetic right-shift HANDLE_TARGET_OPCODE(G_ASHR) +/// Generic integer-base comparison, also applicable to vectors of integers. +HANDLE_TARGET_OPCODE(G_ICMP) + /// Generic BRANCH instruction. This is an unconditional branch. HANDLE_TARGET_OPCODE(G_BR) diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index ee5e8d67c850..a7b6d20c212f 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -100,6 +100,20 @@ bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U) { return true; } +bool IRTranslator::translateICmp(const User &U) { + const CmpInst &CI = cast(U); + unsigned Op0 = getOrCreateVReg(*CI.getOperand(0)); + unsigned Op1 = getOrCreateVReg(*CI.getOperand(1)); + unsigned Res = getOrCreateVReg(CI); + CmpInst::Predicate Pred = CI.getPredicate(); + + assert(isa(CI) && "only integer comparisons supported now"); + assert(CmpInst::isIntPredicate(Pred) && "only int comparisons supported now"); + MIRBuilder.buildICmp({LLT{*CI.getType()}, LLT{*CI.getOperand(0)->getType()}}, + Pred, Res, Op0, Op1); + return true; +} + bool IRTranslator::translateRet(const User &U) { const ReturnInst &RI = cast(U); const Value *Ret = RI.getReturnValue(); diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 5abc652303ea..70a24415f1df 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -184,3 +184,14 @@ MachineInstrBuilder MachineIRBuilder::buildTrunc(LLT Ty, unsigned Res, unsigned Op) { return buildInstr(TargetOpcode::G_TRUNC, Ty).addDef(Res).addUse(Op); } + +MachineInstrBuilder MachineIRBuilder::buildICmp(ArrayRef Tys, + CmpInst::Predicate Pred, + unsigned Res, unsigned Op0, + unsigned Op1) { + return buildInstr(TargetOpcode::G_ICMP, Tys) + .addDef(Res) + .addPredicate(Pred) + .addUse(Op0) + .addUse(Op1); +} diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index 12645710c89d..0850ae7baddf 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -234,6 +234,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("landing-pad", MIToken::kw_landing_pad) .Case("liveins", MIToken::kw_liveins) .Case("successors", MIToken::kw_successors) + .Case("floatpred", MIToken::kw_floatpred) + .Case("intpred", MIToken::kw_intpred) .Default(MIToken::Identifier); } diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 6a0988752813..c0d9561b2e87 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -91,6 +91,8 @@ struct MIToken { kw_landing_pad, kw_liveins, kw_successors, + kw_floatpred, + kw_intpred, // Named metadata keywords md_tbaa, diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 9aeaf2a97b13..0602256683f0 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -155,6 +155,7 @@ public: bool parseIRBlock(BasicBlock *&BB, const Function &F); bool parseBlockAddressOperand(MachineOperand &Dest); bool parseIntrinsicOperand(MachineOperand &Dest); + bool parsePredicateOperand(MachineOperand &Dest); bool parseTargetIndexOperand(MachineOperand &Dest); bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest, @@ -1469,6 +1470,64 @@ bool MIParser::parseIntrinsicOperand(MachineOperand &Dest) { return false; } +bool MIParser::parsePredicateOperand(MachineOperand &Dest) { + assert(Token.is(MIToken::kw_intpred) || Token.is(MIToken::kw_floatpred)); + bool IsFloat = Token.is(MIToken::kw_floatpred); + lex(); + + if (expectAndConsume(MIToken::lparen)) + return error("expected syntax intpred(whatever) or floatpred(whatever"); + + if (Token.isNot(MIToken::Identifier)) + return error("whatever"); + + CmpInst::Predicate Pred; + if (IsFloat) { + Pred = StringSwitch(Token.stringValue()) + .Case("false", CmpInst::FCMP_FALSE) + .Case("oeq", CmpInst::FCMP_OEQ) + .Case("ogt", CmpInst::FCMP_OGT) + .Case("oge", CmpInst::FCMP_OGE) + .Case("olt", CmpInst::FCMP_OLT) + .Case("ole", CmpInst::FCMP_OLE) + .Case("one", CmpInst::FCMP_ONE) + .Case("ord", CmpInst::FCMP_ORD) + .Case("uno", CmpInst::FCMP_UNO) + .Case("ueq", CmpInst::FCMP_UEQ) + .Case("ugt", CmpInst::FCMP_UGT) + .Case("uge", CmpInst::FCMP_UGE) + .Case("ult", CmpInst::FCMP_ULT) + .Case("ule", CmpInst::FCMP_ULE) + .Case("une", CmpInst::FCMP_UNE) + .Case("true", CmpInst::FCMP_TRUE) + .Default(CmpInst::BAD_FCMP_PREDICATE); + if (!CmpInst::isFPPredicate(Pred)) + return error("invalid floating-point predicate"); + } else { + Pred = StringSwitch(Token.stringValue()) + .Case("eq", CmpInst::ICMP_EQ) + .Case("ne", CmpInst::ICMP_NE) + .Case("sgt", CmpInst::ICMP_SGT) + .Case("sge", CmpInst::ICMP_SGE) + .Case("slt", CmpInst::ICMP_SLT) + .Case("sle", CmpInst::ICMP_SLE) + .Case("ugt", CmpInst::ICMP_UGT) + .Case("uge", CmpInst::ICMP_UGE) + .Case("ult", CmpInst::ICMP_ULT) + .Case("ule", CmpInst::ICMP_ULE) + .Default(CmpInst::BAD_ICMP_PREDICATE); + if (!CmpInst::isIntPredicate(Pred)) + return error("invalid integer predicate"); + } + + lex(); + Dest = MachineOperand::CreatePredicate(Pred); + if (!expectAndConsume(MIToken::rparen)) + return error("predicate should be terminated by ')'."); + + return false; +} + bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) { assert(Token.is(MIToken::kw_target_index)); lex(); @@ -1575,6 +1634,9 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest, return parseTargetIndexOperand(Dest); case MIToken::kw_liveout: return parseLiveoutRegisterMaskOperand(Dest); + case MIToken::kw_floatpred: + case MIToken::kw_intpred: + return parsePredicateOperand(Dest); case MIToken::Error: return true; case MIToken::Identifier: diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index d66ac0153c2c..e6c25c0899f2 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -891,6 +891,12 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI, } break; } + case MachineOperand::MO_Predicate: { + auto Pred = static_cast(Op.getPredicate()); + OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred(" + << CmpInst::getPredicateName(Pred) << ')'; + break; + } } } diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 84823071993e..f860bac21696 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -260,6 +260,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { return getMetadata() == Other.getMetadata(); case MachineOperand::MO_IntrinsicID: return getIntrinsicID() == Other.getIntrinsicID(); + case MachineOperand::MO_Predicate: + return getPredicate() == Other.getPredicate(); } llvm_unreachable("Invalid machine operand type"); } @@ -306,6 +308,8 @@ hash_code llvm::hash_value(const MachineOperand &MO) { return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); case MachineOperand::MO_IntrinsicID: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); + case MachineOperand::MO_Predicate: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); } llvm_unreachable("Invalid machine operand type"); } @@ -471,8 +475,12 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, OS << "'; break; } + case MachineOperand::MO_Predicate: { + auto Pred = static_cast(getPredicate()); + OS << '<' << (CmpInst::isIntPredicate(Pred) ? "intpred" : "floatpred") + << CmpInst::getPredicateName(Pred) << '>'; + } } - if (unsigned TF = getTargetFlags()) OS << "[TF=" << TF << ']'; } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 9b2399dd880c..26ca84b43f65 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1,3 +1,4 @@ + //===-- AsmWriter.cpp - Printing LLVM as an assembly file -----------------===// // // The LLVM Compiler Infrastructure @@ -1041,39 +1042,6 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, SlotTracker *Machine, const Module *Context, bool FromValue = false); -static const char *getPredicateText(unsigned predicate) { - const char * pred = "unknown"; - switch (predicate) { - case FCmpInst::FCMP_FALSE: pred = "false"; break; - case FCmpInst::FCMP_OEQ: pred = "oeq"; break; - case FCmpInst::FCMP_OGT: pred = "ogt"; break; - case FCmpInst::FCMP_OGE: pred = "oge"; break; - case FCmpInst::FCMP_OLT: pred = "olt"; break; - case FCmpInst::FCMP_OLE: pred = "ole"; break; - case FCmpInst::FCMP_ONE: pred = "one"; break; - case FCmpInst::FCMP_ORD: pred = "ord"; break; - case FCmpInst::FCMP_UNO: pred = "uno"; break; - case FCmpInst::FCMP_UEQ: pred = "ueq"; break; - case FCmpInst::FCMP_UGT: pred = "ugt"; break; - case FCmpInst::FCMP_UGE: pred = "uge"; break; - case FCmpInst::FCMP_ULT: pred = "ult"; break; - case FCmpInst::FCMP_ULE: pred = "ule"; break; - case FCmpInst::FCMP_UNE: pred = "une"; break; - case FCmpInst::FCMP_TRUE: pred = "true"; break; - case ICmpInst::ICMP_EQ: pred = "eq"; break; - case ICmpInst::ICMP_NE: pred = "ne"; break; - case ICmpInst::ICMP_SGT: pred = "sgt"; break; - case ICmpInst::ICMP_SGE: pred = "sge"; break; - case ICmpInst::ICMP_SLT: pred = "slt"; break; - case ICmpInst::ICMP_SLE: pred = "sle"; break; - case ICmpInst::ICMP_UGT: pred = "ugt"; break; - case ICmpInst::ICMP_UGE: pred = "uge"; break; - case ICmpInst::ICMP_ULT: pred = "ult"; break; - case ICmpInst::ICMP_ULE: pred = "ule"; break; - } - return pred; -} - static void writeAtomicRMWOperation(raw_ostream &Out, AtomicRMWInst::BinOp Op) { switch (Op) { @@ -1349,7 +1317,8 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << CE->getOpcodeName(); WriteOptimizationInfo(Out, CE); if (CE->isCompare()) - Out << ' ' << getPredicateText(CE->getPredicate()); + Out << ' ' << CmpInst::getPredicateName( + static_cast(CE->getPredicate())); Out << " ("; if (const GEPOperator *GEP = dyn_cast(CE)) { @@ -2869,7 +2838,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // Print out the compare instruction predicates if (const CmpInst *CI = dyn_cast(&I)) - Out << ' ' << getPredicateText(CI->getPredicate()); + Out << ' ' << CmpInst::getPredicateName(CI->getPredicate()); // Print out the atomicrmw operation if (const AtomicRMWInst *RMWI = dyn_cast(&I)) diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index b9c693ff19ad..43d7927ce6a8 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -3465,6 +3465,38 @@ CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) { } } +StringRef CmpInst::getPredicateName(Predicate Pred) { + switch (Pred) { + default: return "unknown"; + case FCmpInst::FCMP_FALSE: return "false"; + case FCmpInst::FCMP_OEQ: return "oeq"; + case FCmpInst::FCMP_OGT: return "ogt"; + case FCmpInst::FCMP_OGE: return "oge"; + case FCmpInst::FCMP_OLT: return "olt"; + case FCmpInst::FCMP_OLE: return "ole"; + case FCmpInst::FCMP_ONE: return "one"; + case FCmpInst::FCMP_ORD: return "ord"; + case FCmpInst::FCMP_UNO: return "uno"; + case FCmpInst::FCMP_UEQ: return "ueq"; + case FCmpInst::FCMP_UGT: return "ugt"; + case FCmpInst::FCMP_UGE: return "uge"; + case FCmpInst::FCMP_ULT: return "ult"; + case FCmpInst::FCMP_ULE: return "ule"; + case FCmpInst::FCMP_UNE: return "une"; + case FCmpInst::FCMP_TRUE: return "true"; + case ICmpInst::ICMP_EQ: return "eq"; + case ICmpInst::ICMP_NE: return "ne"; + case ICmpInst::ICMP_SGT: return "sgt"; + case ICmpInst::ICMP_SGE: return "sge"; + case ICmpInst::ICMP_SLT: return "slt"; + case ICmpInst::ICMP_SLE: return "sle"; + case ICmpInst::ICMP_UGT: return "ugt"; + case ICmpInst::ICMP_UGE: return "uge"; + case ICmpInst::ICMP_ULT: return "ult"; + case ICmpInst::ICMP_ULE: return "ule"; + } +} + void ICmpInst::anchor() {} ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) { diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index e74b1ab483b8..062f7c6cb522 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -658,6 +658,7 @@ static bool IsAnAddressOperand(const MachineOperand &MO) { case MachineOperand::MO_CFIIndex: return false; case MachineOperand::MO_IntrinsicID: + case MachineOperand::MO_Predicate: llvm_unreachable("should not exist post-isel"); } llvm_unreachable("unhandled machine operand type"); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index 4aeb30d3afd0..18c38fb68168 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -485,3 +485,15 @@ define void @test_i1_memops(i1* %addr) { store i1 %val, i1* %addr ret void } + +; CHECK-LABEL: name: int_comparison +; CHECK: [[LHS:%[0-9]+]](32) = COPY %w0 +; CHECK: [[RHS:%[0-9]+]](32) = COPY %w1 +; CHECK: [[ADDR:%[0-9]+]](64) = COPY %x2 +; CHECK: [[TST:%[0-9]+]](1) = G_ICMP { s1, s32 } intpred(ne), [[LHS]], [[RHS]] +; CHECK: G_STORE { s1, p0 } [[TST]], [[ADDR]] +define void @int_comparison(i32 %a, i32 %b, i1* %addr) { + %res = icmp ne i32 %a, %b + store i1 %res, i1* %addr + ret void +}